1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-15 10:30:25 -08:00

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.
This commit is contained in:
Po Lu 2023-08-28 13:08:22 +08:00
parent 967fa846fc
commit 2134fd9f27
6 changed files with 79 additions and 76 deletions

View file

@ -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)

View file

@ -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. */

View file

@ -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;

View file

@ -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. */

View file

@ -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);
}
};

View file

@ -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 ();