Correctly display popup dialogs from Emacsclient

* java/org/gnu/emacs/EmacsContextMenu.java (EmacsContextMenu):
Make subclasses final.
* java/org/gnu/emacs/EmacsDialog.java (display1): Check if an
instance of EmacsOpenActivity is open; if it is, try using it to
display the pop up dialog.
* java/org/gnu/emacs/EmacsDialogButtonLayout.java
(EmacsDialogButtonLayout): Make final.
* java/org/gnu/emacs/EmacsHolder.java (EmacsHolder<T>):
Likewise.
* java/org/gnu/emacs/EmacsOpenActivity.java (EmacsOpenActivity):
New field `currentActivity'.
(onCreate, onDestroy, onWindowFocusChanged, onPause): Set that
field as appropriate.
This commit is contained in:
Po Lu 2023-06-08 20:50:02 +08:00
parent b1bd40dce1
commit 1661762784
5 changed files with 85 additions and 8 deletions

View file

@ -58,7 +58,7 @@ public final class EmacsContextMenu
/* The last group ID used for a menu item. */
public int lastGroupId;
private static class Item implements MenuItem.OnMenuItemClickListener
private static final class Item implements MenuItem.OnMenuItemClickListener
{
public int itemID;
public String itemName, tooltip;

View file

@ -68,8 +68,8 @@ public final class EmacsDialog implements DialogInterface.OnDismissListener
/* The menu serial associated with this dialog box. */
private int menuEventSerial;
private class EmacsButton implements View.OnClickListener,
DialogInterface.OnClickListener
private final class EmacsButton implements View.OnClickListener,
DialogInterface.OnClickListener
{
/* Name of this button. */
public String name;
@ -244,13 +244,22 @@ private class EmacsButton implements View.OnClickListener,
if (EmacsActivity.focusedActivities.isEmpty ())
{
/* If focusedActivities is empty then this dialog may have
been displayed immediately after a popup dialog is
been displayed immediately after another popup dialog was
dismissed. Or Emacs might legitimately be in the
background. Try the service context first if possible. */
background, possibly displaying this popup in response to
an Emacsclient request. Try the service context if it will
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;
else if (EmacsOpenActivity.currentActivity != null)
context = EmacsOpenActivity.currentActivity;
else
context = EmacsActivity.lastFocusedActivity;

View file

@ -37,7 +37,7 @@
public class EmacsDialogButtonLayout extends ViewGroup
public final class EmacsDialogButtonLayout extends ViewGroup
{
public
EmacsDialogButtonLayout (Context context)

View file

@ -24,7 +24,7 @@
/* This class serves as a simple reference to an object of type T.
Nothing could be found inside the standard library. */
public class EmacsHolder<T>
public final class EmacsHolder<T>
{
T thing;
};

View file

@ -72,8 +72,17 @@ public final class EmacsOpenActivity extends Activity
DialogInterface.OnCancelListener
{
private static final String TAG = "EmacsOpenActivity";
/* The name of any file that should be opened as EmacsThread starts
Emacs. This is never cleared, even if EmacsOpenActivity is
started a second time, as EmacsThread only starts once. */
public static String fileToOpen;
/* Any currently focused EmacsOpenActivity. Used to show pop ups
while the activity is active and Emacs doesn't have permission to
display over other programs. */
public static EmacsOpenActivity currentActivity;
private class EmacsClientThread extends Thread
{
private ProcessBuilder builder;
@ -362,6 +371,15 @@ private class EmacsClientThread extends Thread
thread.start ();
}
/* Run emacsclient to open the file specified in the Intent that
caused this activity to start.
Determine the name of the file corresponding to the URI specified
in that intent; then, run emacsclient and wait for it to finish.
Finally, display any error message, transfer the focus to an
Emacs frame, and finish the activity. */
@Override
public void
onCreate (Bundle savedInstanceState)
@ -463,10 +481,60 @@ private class EmacsClientThread extends Thread
}
}
/* And start emacsclient. */
/* And start emacsclient. Set `currentActivity' to this now.
Presumably, it will shortly become capable of displaying
dialogs. */
currentActivity = this;
startEmacsClient (fileName);
}
else
finish ();
}
@Override
public void
onDestroy ()
{
Log.d (TAG, "onDestroy: " + this);
/* Clear `currentActivity' if it refers to the activity being
destroyed. */
if (currentActivity == this)
this.currentActivity = null;
super.onDestroy ();
}
@Override
public void
onWindowFocusChanged (boolean isFocused)
{
Log.d (TAG, "onWindowFocusChanged: " + this + ", is now focused: "
+ isFocused);
if (isFocused)
currentActivity = this;
else if (currentActivity == this)
currentActivity = null;
super.onWindowFocusChanged (isFocused);
}
@Override
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. */
if (currentActivity == this)
currentActivity = null;
super.onPause ();
}
}