summaryrefslogtreecommitdiff
path: root/java
diff options
context:
space:
mode:
authorPo Lu <luangruo@yahoo.com>2023-10-10 13:11:14 +0800
committerPo Lu <luangruo@yahoo.com>2023-10-10 13:11:14 +0800
commit336c3674119f61bd78a056476769ce83b97230bb (patch)
tree0af3b8f39dabdf71849c30fe0bf67952305b9319 /java
parent238292d6571402e93d4f7886baac9853011b36f6 (diff)
downloademacs-336c3674119f61bd78a056476769ce83b97230bb.tar.gz
Implement frame restacking under Android
* java/org/gnu/emacs/EmacsActivity.java (invalidateFocus1): Synchronize with window.children for iteration through it. * java/org/gnu/emacs/EmacsService.java (queryTree): Synchronize with windowList for iteration through it. * java/org/gnu/emacs/EmacsView.java (moveChildToBack): Correct formatting mistake. (moveAbove, moveBelow): New functions. * java/org/gnu/emacs/EmacsWindow.java (destroyHandle, reparentTo) (raise, lower): Remedy synchronization blunders. (reconfigure): New function. * src/android.c (android_init_emacs_window): Link with `reconfigure'. (android_reconfigure_wm_window): New wrapper function. * src/androidfns.c (android_frame_restack): New function. (Fandroid_frame_restack): Properly implement this function and expunge outdated comment. * src/androidgui.h (enum android_stack_mode) (enum android_window_changes): New enumerators.
Diffstat (limited to 'java')
-rw-r--r--java/org/gnu/emacs/EmacsActivity.java7
-rw-r--r--java/org/gnu/emacs/EmacsService.java17
-rw-r--r--java/org/gnu/emacs/EmacsView.java40
-rw-r--r--java/org/gnu/emacs/EmacsWindow.java130
4 files changed, 171 insertions, 23 deletions
diff --git a/java/org/gnu/emacs/EmacsActivity.java b/java/org/gnu/emacs/EmacsActivity.java
index cecd9c21d99..f9aa261e355 100644
--- a/java/org/gnu/emacs/EmacsActivity.java
+++ b/java/org/gnu/emacs/EmacsActivity.java
@@ -89,8 +89,11 @@ public class EmacsActivity extends Activity
if (window.view.isFocused ())
focusedWindow = window;
- for (EmacsWindow child : window.children)
- invalidateFocus1 (child);
+ synchronized (window.children)
+ {
+ for (EmacsWindow child : window.children)
+ invalidateFocus1 (child);
+ }
}
public static void
diff --git a/java/org/gnu/emacs/EmacsService.java b/java/org/gnu/emacs/EmacsService.java
index 28b725d0cd0..6fa2ebb3fdb 100644
--- a/java/org/gnu/emacs/EmacsService.java
+++ b/java/org/gnu/emacs/EmacsService.java
@@ -505,15 +505,18 @@ public final class EmacsService extends Service
else
windowList = window.children;
- array = new short[windowList.size () + 1];
- i = 1;
+ synchronized (windowList)
+ {
+ array = new short[windowList.size () + 1];
+ i = 1;
- array[0] = (window == null
- ? 0 : (window.parent != null
- ? window.parent.handle : 0));
+ array[0] = (window == null
+ ? 0 : (window.parent != null
+ ? window.parent.handle : 0));
- for (EmacsWindow treeWindow : windowList)
- array[i++] = treeWindow.handle;
+ for (EmacsWindow treeWindow : windowList)
+ array[i++] = treeWindow.handle;
+ }
return array;
}
diff --git a/java/org/gnu/emacs/EmacsView.java b/java/org/gnu/emacs/EmacsView.java
index d09dcc7e50d..877b1ce2429 100644
--- a/java/org/gnu/emacs/EmacsView.java
+++ b/java/org/gnu/emacs/EmacsView.java
@@ -581,12 +581,12 @@ public final class EmacsView extends ViewGroup
/* The view at 0 is the surface view. */
attachViewToParent (child, 1,
- child.getLayoutParams());
+ child.getLayoutParams ());
}
}
- /* The following two functions must not be called if the view has no
- parent, or is parented to an activity. */
+ /* The following four functions must not be called if the view has
+ no parent, or is parented to an activity. */
public void
raise ()
@@ -615,6 +615,40 @@ public final class EmacsView extends ViewGroup
parent.moveChildToBack (this);
}
+ public void
+ moveAbove (EmacsView view)
+ {
+ EmacsView parent;
+ int index;
+
+ parent = (EmacsView) getParent ();
+
+ if (parent != view.getParent ())
+ throw new IllegalStateException ("Moving view above non-sibling");
+
+ index = parent.indexOfChild (this);
+ parent.detachViewFromParent (index);
+ index = parent.indexOfChild (view);
+ parent.attachViewToParent (this, index + 1, getLayoutParams ());
+ }
+
+ public void
+ moveBelow (EmacsView view)
+ {
+ EmacsView parent;
+ int index;
+
+ parent = (EmacsView) getParent ();
+
+ if (parent != view.getParent ())
+ throw new IllegalStateException ("Moving view above non-sibling");
+
+ index = parent.indexOfChild (this);
+ parent.detachViewFromParent (index);
+ index = parent.indexOfChild (view);
+ parent.attachViewToParent (this, index, getLayoutParams ());
+ }
+
@Override
protected void
onCreateContextMenu (ContextMenu menu)
diff --git a/java/org/gnu/emacs/EmacsWindow.java b/java/org/gnu/emacs/EmacsWindow.java
index 1f28d5f4f53..8d444aa27f5 100644
--- a/java/org/gnu/emacs/EmacsWindow.java
+++ b/java/org/gnu/emacs/EmacsWindow.java
@@ -22,6 +22,7 @@ package org.gnu.emacs;
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;
@@ -93,7 +94,9 @@ public final class EmacsWindow extends EmacsHandleObject
public EmacsWindow parent;
/* List of all children in stacking order. This must be kept
- consistent with their Z order! */
+ consistent with their Z order!
+
+ Synchronize access to this list with itself. */
public ArrayList<EmacsWindow> children;
/* Map between pointer identifiers and last known position. Used to
@@ -165,7 +168,11 @@ public final class EmacsWindow extends EmacsHandleObject
if (parent != null)
{
- parent.children.add (this);
+ synchronized (parent.children)
+ {
+ parent.children.add (this);
+ }
+
EmacsService.SERVICE.runOnUiThread (new Runnable () {
@Override
public void
@@ -214,7 +221,12 @@ public final class EmacsWindow extends EmacsHandleObject
destroyHandle () throws IllegalStateException
{
if (parent != null)
- parent.children.remove (this);
+ {
+ synchronized (parent.children)
+ {
+ parent.children.remove (this);
+ }
+ }
EmacsActivity.invalidateFocus ();
@@ -1163,10 +1175,20 @@ public final class EmacsWindow extends EmacsHandleObject
/* Reparent this window to the other window. */
if (parent != null)
- parent.children.remove (this);
+ {
+ synchronized (parent.children)
+ {
+ parent.children.remove (this);
+ }
+ }
if (otherWindow != null)
- otherWindow.children.add (this);
+ {
+ synchronized (otherWindow.children)
+ {
+ otherWindow.children.add (this);
+ }
+ }
parent = otherWindow;
@@ -1239,9 +1261,12 @@ public final class EmacsWindow extends EmacsHandleObject
if (parent == null)
return;
- /* Remove and add this view again. */
- parent.children.remove (this);
- parent.children.add (this);
+ synchronized (parent.children)
+ {
+ /* Remove and add this view again. */
+ parent.children.remove (this);
+ parent.children.add (this);
+ }
/* Request a relayout. */
EmacsService.SERVICE.runOnUiThread (new Runnable () {
@@ -1261,9 +1286,12 @@ public final class EmacsWindow extends EmacsHandleObject
if (parent == null)
return;
- /* Remove and add this view again. */
- parent.children.remove (this);
- parent.children.add (this);
+ synchronized (parent.children)
+ {
+ /* Remove and add this view again. */
+ parent.children.remove (this);
+ parent.children.add (this);
+ }
/* Request a relayout. */
EmacsService.SERVICE.runOnUiThread (new Runnable () {
@@ -1276,6 +1304,86 @@ public final class EmacsWindow extends EmacsHandleObject
});
}
+ public synchronized void
+ reconfigure (final EmacsWindow window, final int stackMode)
+ {
+ ListIterator<EmacsWindow> iterator;
+ EmacsWindow object;
+
+ /* This does nothing here. */
+ if (parent == null)
+ return;
+
+ /* If window is NULL, call lower or upper subject to
+ stackMode. */
+
+ if (window == null)
+ {
+ if (stackMode == 1) /* ANDROID_BELOW */
+ lower ();
+ else
+ raise ();
+
+ return;
+ }
+
+ /* Otherwise, if window.parent is distinct from this, return. */
+ if (window.parent != this.parent)
+ return;
+
+ /* Synchronize with the parent's child list. Iterate over each
+ item until WINDOW is encountered, before moving this window to
+ the location prescribed by STACKMODE. */
+
+ synchronized (parent.children)
+ {
+ /* Remove this window from parent.children, for it will be
+ reinserted before or after WINDOW. */
+ parent.children.remove (this);
+
+ /* Create an iterator. */
+ iterator = parent.children.listIterator ();
+
+ while (iterator.hasNext ())
+ {
+ object = iterator.next ();
+
+ if (object == window)
+ {
+ /* Now place this before or after the cursor of the
+ iterator. */
+
+ if (stackMode == 0) /* ANDROID_ABOVE */
+ iterator.add (this);
+ else
+ {
+ iterator.previous ();
+ iterator.add (this);
+ }
+
+ /* Effect the same adjustment upon the view
+ hiearchy. */
+
+ EmacsService.SERVICE.runOnUiThread (new Runnable () {
+ @Override
+ public void
+ run ()
+ {
+ if (stackMode == 0)
+ view.moveAbove (window.view);
+ else
+ view.moveBelow (window.view);
+ }
+ });
+ }
+ }
+
+ /* parent.children does not list WINDOW, which should never
+ transpire. */
+ EmacsNative.emacsAbort ();
+ }
+ }
+
public synchronized int[]
getWindowGeometry ()
{