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");
/* 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);
public final void
onWindowFocusChanged (boolean isFocused)
{
- Log.d (TAG, ("onWindowFocusChanged: "
- + (isFocused ? "YES" : "NO")));
-
if (isFocused && !focusedActivities.contains (this))
{
focusedActivities.add (this);
{
int serial;
- Log.d (TAG, "onContextMenuClosed: " + menu);
-
/* See the comment inside onMenuItemClick. */
if (((EmacsContextMenu.wasSubmenuSelected == -2)
public boolean
onMenuItemClick (MenuItem item)
{
- Log.d (TAG, "onMenuItemClick: " + itemName + " (" + itemID + ")");
-
if (subMenu != null)
{
/* Android 6.0 and earlier don't support nested submenus
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. */
public void
onClick (View view)
{
- Log.d (TAG, "onClicked " + this);
-
wasButtonClicked = true;
EmacsNative.sendContextMenu ((short) 0, id, menuEventSerial);
dismissDialog.dismiss ();
public void
onClick (DialogInterface dialog, int which)
{
- Log.d (TAG, "onClicked " + this);
-
wasButtonClicked = true;
EmacsNative.sendContextMenu ((short) 0, id, menuEventSerial);
}
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;
consistently. */
context = EmacsActivity.focusedActivities.get (0);
- Log.d (TAG, "display1: using context " + context);
-
dialog = dismissDialog = toAlertDialog (context);
try
public void
onDismiss (DialogInterface dialog)
{
- Log.d (TAG, "onDismiss: " + this);
-
if (wasButtonClicked)
return;
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;
}
public void
onDestroy ()
{
- Log.d (TAG, "onDestroy: " + this);
-
/* Clear `currentActivity' if it refers to the activity being
destroyed. */
public void
onWindowFocusChanged (boolean isFocused)
{
- Log.d (TAG, "onWindowFocusChanged: " + this + ", is now focused: "
- + isFocused);
-
if (isFocused)
currentActivity = this;
else if (currentActivity == this)
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. */
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;
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. */
View child;
Rect windowRect;
boolean needExpose;
+ WindowInsets rootWindowInsets;
count = getChildCount ();
needExpose = false;
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)
return window.onTouchEvent (motion);
}
+\f
+
private void
moveChildToBack (View child)
{
parent = (EmacsView) getParent ();
- Log.d (TAG, "raise: parent " + parent);
-
if (parent.indexOfChild (this)
== parent.getChildCount () - 1)
return;
parent = (EmacsView) getParent ();
- Log.d (TAG, "lower: parent " + parent);
-
if (parent.indexOfChild (this) == 1)
return;
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)
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. */
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);
+ }
};
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);
}
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;
}
EmacsService.SERVICE.startActivity (intent,
options.toBundle ());
}
-
- Log.d (TAG, "registerWindow: startActivity");
}
public void
{
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);
}
{
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 ();
}
{
EmacsWindow window;
- Log.d (TAG, "noticeIconified " + consumer);
-
/* If a window is attached, send the appropriate iconification
events. */
window = consumer.getAttachedWindow ();
{
EmacsWindow window;
- Log.d (TAG, "noticeDeiconified " + consumer);
-
/* If a window is attached, send the appropriate iconification
events. */
window = consumer.getAttachedWindow ();