From: Po Lu Date: Mon, 28 Aug 2023 05:08:22 +0000 (+0800) Subject: Update Android port X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=2134fd9f2767f6c0d14d3ad45cabcb963a06a8ed;p=emacs.git Update Android port * java/org/gnu/emacs/EmacsActivity.java (attachWindow, onDestroy) (onWindowFocusChanged, onContextMenuClosed): * java/org/gnu/emacs/EmacsContextMenu.java (onMenuItemClick): * java/org/gnu/emacs/EmacsDialog.java (onClick, display1, onDismiss): * java/org/gnu/emacs/EmacsOpenActivity.java (checkReadableOrCopy) (onDestroy, onWindowFocusChanged, onPause): * java/org/gnu/emacs/EmacsWindowAttachmentManager.java (registerWindow, removeWindowConsumer, detachWindow) (noticeIconified, noticeDeiconified): Remove superfluous debugging code now that the Android port is stable. * java/org/gnu/emacs/EmacsView.java (onLayout): Detect if the IME is hidden while a toplevel window is focused, and clear isCurrentlyTextEditor in that case. (onApplyWindowInsets): New function. (raise, lower, popupMenu, onCreateInputConnection): Delete aforementioned debugging code. --- diff --git a/java/org/gnu/emacs/EmacsActivity.java b/java/org/gnu/emacs/EmacsActivity.java index 4ddf51fbb20..cecd9c21d99 100644 --- a/java/org/gnu/emacs/EmacsActivity.java +++ b/java/org/gnu/emacs/EmacsActivity.java @@ -149,8 +149,6 @@ public class EmacsActivity extends Activity public final void attachWindow (EmacsWindow child) { - Log.d (TAG, "attachWindow: " + child); - if (window != null) throw new IllegalStateException ("trying to attach window when one" + " already exists"); @@ -257,7 +255,6 @@ public class EmacsActivity extends Activity /* The activity will die shortly hereafter. If there is a window attached, close it now. */ - Log.d (TAG, "onDestroy " + this); isMultitask = this instanceof EmacsMultitaskActivity; manager.removeWindowConsumer (this, isMultitask || isFinishing ()); focusedActivities.remove (this); @@ -274,9 +271,6 @@ public class EmacsActivity extends Activity public final void onWindowFocusChanged (boolean isFocused) { - Log.d (TAG, ("onWindowFocusChanged: " - + (isFocused ? "YES" : "NO"))); - if (isFocused && !focusedActivities.contains (this)) { focusedActivities.add (this); @@ -323,8 +317,6 @@ public class EmacsActivity extends Activity { int serial; - Log.d (TAG, "onContextMenuClosed: " + menu); - /* See the comment inside onMenuItemClick. */ if (((EmacsContextMenu.wasSubmenuSelected == -2) diff --git a/java/org/gnu/emacs/EmacsContextMenu.java b/java/org/gnu/emacs/EmacsContextMenu.java index 46eddeeda3d..c5b87aa804a 100644 --- a/java/org/gnu/emacs/EmacsContextMenu.java +++ b/java/org/gnu/emacs/EmacsContextMenu.java @@ -72,8 +72,6 @@ public final class EmacsContextMenu public boolean onMenuItemClick (MenuItem item) { - Log.d (TAG, "onMenuItemClick: " + itemName + " (" + itemID + ")"); - if (subMenu != null) { /* Android 6.0 and earlier don't support nested submenus @@ -81,8 +79,6 @@ public final class EmacsContextMenu if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { - Log.d (TAG, "onMenuItemClick: displaying submenu " + subMenu); - /* Still set wasSubmenuSelected -- if not set, the dismissal of this context menu will result in a context menu event being sent. */ diff --git a/java/org/gnu/emacs/EmacsDialog.java b/java/org/gnu/emacs/EmacsDialog.java index 2291207fbcc..af3bf538410 100644 --- a/java/org/gnu/emacs/EmacsDialog.java +++ b/java/org/gnu/emacs/EmacsDialog.java @@ -88,8 +88,6 @@ public final class EmacsDialog implements DialogInterface.OnDismissListener public void onClick (View view) { - Log.d (TAG, "onClicked " + this); - wasButtonClicked = true; EmacsNative.sendContextMenu ((short) 0, id, menuEventSerial); dismissDialog.dismiss (); @@ -99,8 +97,6 @@ public final class EmacsDialog implements DialogInterface.OnDismissListener public void onClick (DialogInterface dialog, int which) { - Log.d (TAG, "onClicked " + this); - wasButtonClicked = true; EmacsNative.sendContextMenu ((short) 0, id, menuEventSerial); } @@ -300,10 +296,6 @@ public final class EmacsDialog implements DialogInterface.OnDismissListener work, then any focused EmacsOpenActivity, and finally the last EmacsActivity to be focused. */ - Log.d (TAG, "display1: no focused activities..."); - Log.d (TAG, ("display1: EmacsOpenActivity.currentActivity: " - + EmacsOpenActivity.currentActivity)); - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M || Settings.canDrawOverlays (EmacsService.SERVICE)) context = EmacsService.SERVICE; @@ -321,8 +313,6 @@ public final class EmacsDialog implements DialogInterface.OnDismissListener consistently. */ context = EmacsActivity.focusedActivities.get (0); - Log.d (TAG, "display1: using context " + context); - dialog = dismissDialog = toAlertDialog (context); try @@ -418,8 +408,6 @@ public final class EmacsDialog implements DialogInterface.OnDismissListener public void onDismiss (DialogInterface dialog) { - Log.d (TAG, "onDismiss: " + this); - if (wasButtonClicked) return; diff --git a/java/org/gnu/emacs/EmacsOpenActivity.java b/java/org/gnu/emacs/EmacsOpenActivity.java index 3832cd2faab..ea503ebd120 100644 --- a/java/org/gnu/emacs/EmacsOpenActivity.java +++ b/java/org/gnu/emacs/EmacsOpenActivity.java @@ -232,19 +232,14 @@ public final class EmacsOpenActivity extends Activity int read; String content; - Log.d (TAG, "checkReadableOrCopy: " + file); - inFile = new File (file); if (inFile.canRead ()) return file; - Log.d (TAG, "checkReadableOrCopy: NO"); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { content = EmacsService.buildContentName (uri); - Log.d (TAG, "checkReadableOrCopy: " + content); return content; } @@ -509,8 +504,6 @@ public final class EmacsOpenActivity extends Activity public void onDestroy () { - Log.d (TAG, "onDestroy: " + this); - /* Clear `currentActivity' if it refers to the activity being destroyed. */ @@ -524,9 +517,6 @@ public final class EmacsOpenActivity extends Activity public void onWindowFocusChanged (boolean isFocused) { - Log.d (TAG, "onWindowFocusChanged: " + this + ", is now focused: " - + isFocused); - if (isFocused) currentActivity = this; else if (currentActivity == this) @@ -539,8 +529,6 @@ public final class EmacsOpenActivity extends Activity public void onPause () { - Log.d (TAG, "onPause: " + this); - /* XXX: clear currentActivity here as well; I don't know whether or not onWindowFocusChanged is always called prior to this. */ diff --git a/java/org/gnu/emacs/EmacsView.java b/java/org/gnu/emacs/EmacsView.java index f964f096d88..5a4bcbaa005 100644 --- a/java/org/gnu/emacs/EmacsView.java +++ b/java/org/gnu/emacs/EmacsView.java @@ -29,6 +29,7 @@ import android.view.KeyEvent; import android.view.MotionEvent; import android.view.ViewGroup; import android.view.ViewTreeObserver; +import android.view.WindowInsets; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; @@ -302,6 +303,26 @@ public final class EmacsView extends ViewGroup super.setMeasuredDimension (width, height); } + /* Return whether this view's window is focused. This is made + necessary by Android 11's unreliable dispatch of + onWindowFocusChanged prior to gesture navigation away from a + frame. */ + + public boolean + checkWindowFocus () + { + EmacsActivity activity; + Object consumer; + + consumer = window.getAttachedConsumer (); + + if (!(consumer instanceof EmacsActivity)) + return false; + + activity = (EmacsActivity) consumer; + return activity.hasWindowFocus (); + } + /* 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. */ @@ -315,6 +336,7 @@ public final class EmacsView extends ViewGroup View child; Rect windowRect; boolean needExpose; + WindowInsets rootWindowInsets; count = getChildCount (); needExpose = false; @@ -349,14 +371,37 @@ public final class EmacsView extends ViewGroup if (right - left > oldMeasuredWidth || bottom - top > oldMeasuredHeight) needExpose = true; + + /* This might return NULL if this view is not attached. */ + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) + { + /* If a toplevel view is focused and isCurrentlyTextEditor + is enabled when the IME is hidden, clear + isCurrentlyTextEditor so it isn't shown again if the + user dismisses Emacs before returning. */ + rootWindowInsets = getRootWindowInsets (); + + if (isCurrentlyTextEditor + && rootWindowInsets != null + && isAttachedToWindow + && !rootWindowInsets.isVisible (WindowInsets.Type.ime ()) + /* N.B. that the keyboard is dismissed during gesture + navigation under Android 30, but the system is + quite tempermental regarding whether the window is + focused at that point. Ideally + isCurrentlyTextEditor shouldn't be reset in that + case, but detecting that situation appears to be + impossible. Sigh. */ + && (window == EmacsActivity.focusedWindow + && hasWindowFocus ())) + isCurrentlyTextEditor = false; + } } for (i = 0; i < count; ++i) { child = getChildAt (i); - Log.d (TAG, "onLayout: " + child); - if (child == surfaceView) child.layout (0, 0, right - left, bottom - top); else if (child.getVisibility () != GONE) @@ -491,6 +536,8 @@ public final class EmacsView extends ViewGroup return window.onTouchEvent (motion); } + + private void moveChildToBack (View child) { @@ -518,8 +565,6 @@ public final class EmacsView extends ViewGroup parent = (EmacsView) getParent (); - Log.d (TAG, "raise: parent " + parent); - if (parent.indexOfChild (this) == parent.getChildCount () - 1) return; @@ -534,8 +579,6 @@ public final class EmacsView extends ViewGroup parent = (EmacsView) getParent (); - Log.d (TAG, "lower: parent " + parent); - if (parent.indexOfChild (this) == 1) return; @@ -562,9 +605,6 @@ public final class EmacsView extends ViewGroup contextMenu = menu; popupActive = true; - Log.d (TAG, "popupMenu: " + menu + " @" + xPosition - + ", " + yPosition + " " + force); - /* Use showContextMenu (float, float) on N to get actual popup behavior. */ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) @@ -700,14 +740,8 @@ public final class EmacsView extends ViewGroup selection = EmacsService.viewGetSelection (window.handle); - if (selection != null) - Log.d (TAG, "onCreateInputConnection: current selection is: " - + selection[0] + ", by " + selection[1]); - else + if (selection == null) { - Log.d (TAG, "onCreateInputConnection: current selection could" - + " not be retrieved."); - /* If the selection could not be obtained, return 0 by 0. However, ask for the selection position to be updated as soon as possible. */ @@ -780,4 +814,33 @@ public final class EmacsView extends ViewGroup window.notifyContentRectPosition (locations[0], locations[1]); } + + @Override + public WindowInsets + onApplyWindowInsets (WindowInsets insets) + { + WindowInsets rootWindowInsets; + + /* This function is called when window insets change, which + encompasses input method visibility changes under Android 30 + and later. If a toplevel view is focused and + isCurrentlyTextEditor is enabled when the IME is hidden, clear + isCurrentlyTextEditor so it isn't shown again if the user + dismisses Emacs before returning. */ + + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) + return super.onApplyWindowInsets (insets); + + /* This might return NULL if this view is not attached. */ + rootWindowInsets = getRootWindowInsets (); + + if (isCurrentlyTextEditor + && rootWindowInsets != null + && isAttachedToWindow + && !rootWindowInsets.isVisible (WindowInsets.Type.ime ()) + && window == EmacsActivity.focusedWindow) + isCurrentlyTextEditor = false; + + return super.onApplyWindowInsets (insets); + } }; diff --git a/java/org/gnu/emacs/EmacsWindowAttachmentManager.java b/java/org/gnu/emacs/EmacsWindowAttachmentManager.java index bc96de7fe1a..4ba5b35aacf 100644 --- a/java/org/gnu/emacs/EmacsWindowAttachmentManager.java +++ b/java/org/gnu/emacs/EmacsWindowAttachmentManager.java @@ -87,21 +87,17 @@ public final class EmacsWindowAttachmentManager public void registerWindowConsumer (WindowConsumer consumer) { - Log.d (TAG, "registerWindowConsumer " + consumer); - consumers.add (consumer); for (EmacsWindow window : windows) { if (window.getAttachedConsumer () == null) { - Log.d (TAG, "registerWindowConsumer: attaching " + window); consumer.attachWindow (window); return; } } - Log.d (TAG, "registerWindowConsumer: sendWindowAction 0, 0"); EmacsNative.sendWindowAction ((short) 0, 0); } @@ -111,21 +107,16 @@ public final class EmacsWindowAttachmentManager Intent intent; ActivityOptions options; - Log.d (TAG, "registerWindow (maybe): " + window); - if (windows.contains (window)) /* The window is already registered. */ return; - Log.d (TAG, "registerWindow: " + window); - windows.add (window); for (WindowConsumer consumer : consumers) { if (consumer.getAttachedWindow () == null) { - Log.d (TAG, "registerWindow: attaching " + consumer); consumer.attachWindow (window); return; } @@ -147,8 +138,6 @@ public final class EmacsWindowAttachmentManager EmacsService.SERVICE.startActivity (intent, options.toBundle ()); } - - Log.d (TAG, "registerWindow: startActivity"); } public void @@ -156,19 +145,14 @@ public final class EmacsWindowAttachmentManager { EmacsWindow window; - Log.d (TAG, "removeWindowConsumer " + consumer); - window = consumer.getAttachedWindow (); if (window != null) { - Log.d (TAG, "removeWindowConsumer: detaching " + window); - consumer.detachWindow (); window.onActivityDetached (isFinishing); } - Log.d (TAG, "removeWindowConsumer: removing " + consumer); consumers.remove (consumer); } @@ -177,14 +161,10 @@ public final class EmacsWindowAttachmentManager { WindowConsumer consumer; - Log.d (TAG, "detachWindow " + window); - if (window.getAttachedConsumer () != null) { consumer = window.getAttachedConsumer (); - Log.d (TAG, "detachWindow: removing" + consumer); - consumers.remove (consumer); consumer.destroy (); } @@ -197,8 +177,6 @@ public final class EmacsWindowAttachmentManager { EmacsWindow window; - Log.d (TAG, "noticeIconified " + consumer); - /* If a window is attached, send the appropriate iconification events. */ window = consumer.getAttachedWindow (); @@ -212,8 +190,6 @@ public final class EmacsWindowAttachmentManager { EmacsWindow window; - Log.d (TAG, "noticeDeiconified " + consumer); - /* If a window is attached, send the appropriate iconification events. */ window = consumer.getAttachedWindow ();