diff options
| author | Po Lu | 2023-10-10 13:11:14 +0800 |
|---|---|---|
| committer | Po Lu | 2023-10-10 13:11:14 +0800 |
| commit | 336c3674119f61bd78a056476769ce83b97230bb (patch) | |
| tree | 0af3b8f39dabdf71849c30fe0bf67952305b9319 /java | |
| parent | 238292d6571402e93d4f7886baac9853011b36f6 (diff) | |
| download | emacs-336c3674119f61bd78a056476769ce83b97230bb.tar.gz emacs-336c3674119f61bd78a056476769ce83b97230bb.zip | |
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 | |||
| 89 | if (window.view.isFocused ()) | 89 | if (window.view.isFocused ()) |
| 90 | focusedWindow = window; | 90 | focusedWindow = window; |
| 91 | 91 | ||
| 92 | for (EmacsWindow child : window.children) | 92 | synchronized (window.children) |
| 93 | invalidateFocus1 (child); | 93 | { |
| 94 | for (EmacsWindow child : window.children) | ||
| 95 | invalidateFocus1 (child); | ||
| 96 | } | ||
| 94 | } | 97 | } |
| 95 | 98 | ||
| 96 | public static void | 99 | 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 | |||
| 505 | else | 505 | else |
| 506 | windowList = window.children; | 506 | windowList = window.children; |
| 507 | 507 | ||
| 508 | array = new short[windowList.size () + 1]; | 508 | synchronized (windowList) |
| 509 | i = 1; | 509 | { |
| 510 | array = new short[windowList.size () + 1]; | ||
| 511 | i = 1; | ||
| 510 | 512 | ||
| 511 | array[0] = (window == null | 513 | array[0] = (window == null |
| 512 | ? 0 : (window.parent != null | 514 | ? 0 : (window.parent != null |
| 513 | ? window.parent.handle : 0)); | 515 | ? window.parent.handle : 0)); |
| 514 | 516 | ||
| 515 | for (EmacsWindow treeWindow : windowList) | 517 | for (EmacsWindow treeWindow : windowList) |
| 516 | array[i++] = treeWindow.handle; | 518 | array[i++] = treeWindow.handle; |
| 519 | } | ||
| 517 | 520 | ||
| 518 | return array; | 521 | return array; |
| 519 | } | 522 | } |
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 | |||
| 581 | 581 | ||
| 582 | /* The view at 0 is the surface view. */ | 582 | /* The view at 0 is the surface view. */ |
| 583 | attachViewToParent (child, 1, | 583 | attachViewToParent (child, 1, |
| 584 | child.getLayoutParams()); | 584 | child.getLayoutParams ()); |
| 585 | } | 585 | } |
| 586 | } | 586 | } |
| 587 | 587 | ||
| 588 | /* The following two functions must not be called if the view has no | 588 | /* The following four functions must not be called if the view has |
| 589 | parent, or is parented to an activity. */ | 589 | no parent, or is parented to an activity. */ |
| 590 | 590 | ||
| 591 | public void | 591 | public void |
| 592 | raise () | 592 | raise () |
| @@ -615,6 +615,40 @@ public final class EmacsView extends ViewGroup | |||
| 615 | parent.moveChildToBack (this); | 615 | parent.moveChildToBack (this); |
| 616 | } | 616 | } |
| 617 | 617 | ||
| 618 | public void | ||
| 619 | moveAbove (EmacsView view) | ||
| 620 | { | ||
| 621 | EmacsView parent; | ||
| 622 | int index; | ||
| 623 | |||
| 624 | parent = (EmacsView) getParent (); | ||
| 625 | |||
| 626 | if (parent != view.getParent ()) | ||
| 627 | throw new IllegalStateException ("Moving view above non-sibling"); | ||
| 628 | |||
| 629 | index = parent.indexOfChild (this); | ||
| 630 | parent.detachViewFromParent (index); | ||
| 631 | index = parent.indexOfChild (view); | ||
| 632 | parent.attachViewToParent (this, index + 1, getLayoutParams ()); | ||
| 633 | } | ||
| 634 | |||
| 635 | public void | ||
| 636 | moveBelow (EmacsView view) | ||
| 637 | { | ||
| 638 | EmacsView parent; | ||
| 639 | int index; | ||
| 640 | |||
| 641 | parent = (EmacsView) getParent (); | ||
| 642 | |||
| 643 | if (parent != view.getParent ()) | ||
| 644 | throw new IllegalStateException ("Moving view above non-sibling"); | ||
| 645 | |||
| 646 | index = parent.indexOfChild (this); | ||
| 647 | parent.detachViewFromParent (index); | ||
| 648 | index = parent.indexOfChild (view); | ||
| 649 | parent.attachViewToParent (this, index, getLayoutParams ()); | ||
| 650 | } | ||
| 651 | |||
| 618 | @Override | 652 | @Override |
| 619 | protected void | 653 | protected void |
| 620 | onCreateContextMenu (ContextMenu menu) | 654 | 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; | |||
| 22 | import java.lang.IllegalStateException; | 22 | import java.lang.IllegalStateException; |
| 23 | import java.util.ArrayList; | 23 | import java.util.ArrayList; |
| 24 | import java.util.List; | 24 | import java.util.List; |
| 25 | import java.util.ListIterator; | ||
| 25 | import java.util.HashMap; | 26 | import java.util.HashMap; |
| 26 | import java.util.LinkedHashMap; | 27 | import java.util.LinkedHashMap; |
| 27 | import java.util.Map; | 28 | import java.util.Map; |
| @@ -93,7 +94,9 @@ public final class EmacsWindow extends EmacsHandleObject | |||
| 93 | public EmacsWindow parent; | 94 | public EmacsWindow parent; |
| 94 | 95 | ||
| 95 | /* List of all children in stacking order. This must be kept | 96 | /* List of all children in stacking order. This must be kept |
| 96 | consistent with their Z order! */ | 97 | consistent with their Z order! |
| 98 | |||
| 99 | Synchronize access to this list with itself. */ | ||
| 97 | public ArrayList<EmacsWindow> children; | 100 | public ArrayList<EmacsWindow> children; |
| 98 | 101 | ||
| 99 | /* Map between pointer identifiers and last known position. Used to | 102 | /* Map between pointer identifiers and last known position. Used to |
| @@ -165,7 +168,11 @@ public final class EmacsWindow extends EmacsHandleObject | |||
| 165 | 168 | ||
| 166 | if (parent != null) | 169 | if (parent != null) |
| 167 | { | 170 | { |
| 168 | parent.children.add (this); | 171 | synchronized (parent.children) |
| 172 | { | ||
| 173 | parent.children.add (this); | ||
| 174 | } | ||
| 175 | |||
| 169 | EmacsService.SERVICE.runOnUiThread (new Runnable () { | 176 | EmacsService.SERVICE.runOnUiThread (new Runnable () { |
| 170 | @Override | 177 | @Override |
| 171 | public void | 178 | public void |
| @@ -214,7 +221,12 @@ public final class EmacsWindow extends EmacsHandleObject | |||
| 214 | destroyHandle () throws IllegalStateException | 221 | destroyHandle () throws IllegalStateException |
| 215 | { | 222 | { |
| 216 | if (parent != null) | 223 | if (parent != null) |
| 217 | parent.children.remove (this); | 224 | { |
| 225 | synchronized (parent.children) | ||
| 226 | { | ||
| 227 | parent.children.remove (this); | ||
| 228 | } | ||
| 229 | } | ||
| 218 | 230 | ||
| 219 | EmacsActivity.invalidateFocus (); | 231 | EmacsActivity.invalidateFocus (); |
| 220 | 232 | ||
| @@ -1163,10 +1175,20 @@ public final class EmacsWindow extends EmacsHandleObject | |||
| 1163 | /* Reparent this window to the other window. */ | 1175 | /* Reparent this window to the other window. */ |
| 1164 | 1176 | ||
| 1165 | if (parent != null) | 1177 | if (parent != null) |
| 1166 | parent.children.remove (this); | 1178 | { |
| 1179 | synchronized (parent.children) | ||
| 1180 | { | ||
| 1181 | parent.children.remove (this); | ||
| 1182 | } | ||
| 1183 | } | ||
| 1167 | 1184 | ||
| 1168 | if (otherWindow != null) | 1185 | if (otherWindow != null) |
| 1169 | otherWindow.children.add (this); | 1186 | { |
| 1187 | synchronized (otherWindow.children) | ||
| 1188 | { | ||
| 1189 | otherWindow.children.add (this); | ||
| 1190 | } | ||
| 1191 | } | ||
| 1170 | 1192 | ||
| 1171 | parent = otherWindow; | 1193 | parent = otherWindow; |
| 1172 | 1194 | ||
| @@ -1239,9 +1261,12 @@ public final class EmacsWindow extends EmacsHandleObject | |||
| 1239 | if (parent == null) | 1261 | if (parent == null) |
| 1240 | return; | 1262 | return; |
| 1241 | 1263 | ||
| 1242 | /* Remove and add this view again. */ | 1264 | synchronized (parent.children) |
| 1243 | parent.children.remove (this); | 1265 | { |
| 1244 | parent.children.add (this); | 1266 | /* Remove and add this view again. */ |
| 1267 | parent.children.remove (this); | ||
| 1268 | parent.children.add (this); | ||
| 1269 | } | ||
| 1245 | 1270 | ||
| 1246 | /* Request a relayout. */ | 1271 | /* Request a relayout. */ |
| 1247 | EmacsService.SERVICE.runOnUiThread (new Runnable () { | 1272 | EmacsService.SERVICE.runOnUiThread (new Runnable () { |
| @@ -1261,9 +1286,12 @@ public final class EmacsWindow extends EmacsHandleObject | |||
| 1261 | if (parent == null) | 1286 | if (parent == null) |
| 1262 | return; | 1287 | return; |
| 1263 | 1288 | ||
| 1264 | /* Remove and add this view again. */ | 1289 | synchronized (parent.children) |
| 1265 | parent.children.remove (this); | 1290 | { |
| 1266 | parent.children.add (this); | 1291 | /* Remove and add this view again. */ |
| 1292 | parent.children.remove (this); | ||
| 1293 | parent.children.add (this); | ||
| 1294 | } | ||
| 1267 | 1295 | ||
| 1268 | /* Request a relayout. */ | 1296 | /* Request a relayout. */ |
| 1269 | EmacsService.SERVICE.runOnUiThread (new Runnable () { | 1297 | EmacsService.SERVICE.runOnUiThread (new Runnable () { |
| @@ -1276,6 +1304,86 @@ public final class EmacsWindow extends EmacsHandleObject | |||
| 1276 | }); | 1304 | }); |
| 1277 | } | 1305 | } |
| 1278 | 1306 | ||
| 1307 | public synchronized void | ||
| 1308 | reconfigure (final EmacsWindow window, final int stackMode) | ||
| 1309 | { | ||
| 1310 | ListIterator<EmacsWindow> iterator; | ||
| 1311 | EmacsWindow object; | ||
| 1312 | |||
| 1313 | /* This does nothing here. */ | ||
| 1314 | if (parent == null) | ||
| 1315 | return; | ||
| 1316 | |||
| 1317 | /* If window is NULL, call lower or upper subject to | ||
| 1318 | stackMode. */ | ||
| 1319 | |||
| 1320 | if (window == null) | ||
| 1321 | { | ||
| 1322 | if (stackMode == 1) /* ANDROID_BELOW */ | ||
| 1323 | lower (); | ||
| 1324 | else | ||
| 1325 | raise (); | ||
| 1326 | |||
| 1327 | return; | ||
| 1328 | } | ||
| 1329 | |||
| 1330 | /* Otherwise, if window.parent is distinct from this, return. */ | ||
| 1331 | if (window.parent != this.parent) | ||
| 1332 | return; | ||
| 1333 | |||
| 1334 | /* Synchronize with the parent's child list. Iterate over each | ||
| 1335 | item until WINDOW is encountered, before moving this window to | ||
| 1336 | the location prescribed by STACKMODE. */ | ||
| 1337 | |||
| 1338 | synchronized (parent.children) | ||
| 1339 | { | ||
| 1340 | /* Remove this window from parent.children, for it will be | ||
| 1341 | reinserted before or after WINDOW. */ | ||
| 1342 | parent.children.remove (this); | ||
| 1343 | |||
| 1344 | /* Create an iterator. */ | ||
| 1345 | iterator = parent.children.listIterator (); | ||
| 1346 | |||
| 1347 | while (iterator.hasNext ()) | ||
| 1348 | { | ||
| 1349 | object = iterator.next (); | ||
| 1350 | |||
| 1351 | if (object == window) | ||
| 1352 | { | ||
| 1353 | /* Now place this before or after the cursor of the | ||
| 1354 | iterator. */ | ||
| 1355 | |||
| 1356 | if (stackMode == 0) /* ANDROID_ABOVE */ | ||
| 1357 | iterator.add (this); | ||
| 1358 | else | ||
| 1359 | { | ||
| 1360 | iterator.previous (); | ||
| 1361 | iterator.add (this); | ||
| 1362 | } | ||
| 1363 | |||
| 1364 | /* Effect the same adjustment upon the view | ||
| 1365 | hiearchy. */ | ||
| 1366 | |||
| 1367 | EmacsService.SERVICE.runOnUiThread (new Runnable () { | ||
| 1368 | @Override | ||
| 1369 | public void | ||
| 1370 | run () | ||
| 1371 | { | ||
| 1372 | if (stackMode == 0) | ||
| 1373 | view.moveAbove (window.view); | ||
| 1374 | else | ||
| 1375 | view.moveBelow (window.view); | ||
| 1376 | } | ||
| 1377 | }); | ||
| 1378 | } | ||
| 1379 | } | ||
| 1380 | |||
| 1381 | /* parent.children does not list WINDOW, which should never | ||
| 1382 | transpire. */ | ||
| 1383 | EmacsNative.emacsAbort (); | ||
| 1384 | } | ||
| 1385 | } | ||
| 1386 | |||
| 1279 | public synchronized int[] | 1387 | public synchronized int[] |
| 1280 | getWindowGeometry () | 1388 | getWindowGeometry () |
| 1281 | { | 1389 | { |