diff options
author | Po Lu <luangruo@yahoo.com> | 2023-10-10 13:11:14 +0800 |
---|---|---|
committer | Po Lu <luangruo@yahoo.com> | 2023-10-10 13:11:14 +0800 |
commit | 336c3674119f61bd78a056476769ce83b97230bb (patch) | |
tree | 0af3b8f39dabdf71849c30fe0bf67952305b9319 /java | |
parent | 238292d6571402e93d4f7886baac9853011b36f6 (diff) | |
download | emacs-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.java | 7 | ||||
-rw-r--r-- | java/org/gnu/emacs/EmacsService.java | 17 | ||||
-rw-r--r-- | java/org/gnu/emacs/EmacsView.java | 40 | ||||
-rw-r--r-- | java/org/gnu/emacs/EmacsWindow.java | 130 |
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 () { |