diff options
| author | Po Lu | 2025-02-19 20:40:12 +0800 |
|---|---|---|
| committer | Po Lu | 2025-02-19 20:40:12 +0800 |
| commit | ded77feffface0c167edacf0d807273f3d4878db (patch) | |
| tree | 7849fa1827ed2ad92420d5e43589a8a43d0eaca9 /java | |
| parent | e97be722d392056b6ef9e47664273ee2ca7df374 (diff) | |
| download | emacs-ded77feffface0c167edacf0d807273f3d4878db.tar.gz emacs-ded77feffface0c167edacf0d807273f3d4878db.zip | |
Fix remaining Android bugs reported over the past months
* java/org/gnu/emacs/EmacsActivity.java (attachWindow):
Guarantee that child windows promoted to toplevels receive
layout parameters that direct them to receive their parents'
dimensions. Otherwise, the size of the window as a child is
retained on Huawei HarmonyOS 4.2 and possibly other Android
distributions.
* java/org/gnu/emacs/EmacsService.java (updateCursorAnchorInfo):
Run anchor updates on the UI thread, as
`InputMethodManager#updateCursorAnchorInfo' is liable to call
`View#requestLayout'.
* java/org/gnu/emacs/EmacsView.java (onMeasure): Always call
`measureChildren', or child frames' onLayout handlers might not
be invoked after they request a layout cycle and are duly
processed in `onLayout'.
(swapBuffers): Delete erroneous commentary.
* java/org/gnu/emacs/EmacsWindow.java (viewLayout): If
overrideRedirect, don't inadvertently clear rect.left and
rect.top by recording the window's WM window-relative position.
Fix typos.
(reparentTo): Invalidate focus after transferring frame.
(translateCoordinates): Account for override-redirect windows.
Mostly important for mouse-drag-and-drop-region.
Diffstat (limited to 'java')
| -rw-r--r-- | java/org/gnu/emacs/EmacsActivity.java | 11 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsService.java | 15 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsView.java | 9 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsWindow.java | 56 |
4 files changed, 69 insertions, 22 deletions
diff --git a/java/org/gnu/emacs/EmacsActivity.java b/java/org/gnu/emacs/EmacsActivity.java index 8a5ccb4625b..9f36561cc02 100644 --- a/java/org/gnu/emacs/EmacsActivity.java +++ b/java/org/gnu/emacs/EmacsActivity.java | |||
| @@ -179,6 +179,8 @@ public class EmacsActivity extends Activity | |||
| 179 | public final void | 179 | public final void |
| 180 | attachWindow (EmacsWindow child) | 180 | attachWindow (EmacsWindow child) |
| 181 | { | 181 | { |
| 182 | FrameLayout.LayoutParams defaultParams; | ||
| 183 | |||
| 182 | if (window != null) | 184 | if (window != null) |
| 183 | throw new IllegalStateException ("trying to attach window when one" | 185 | throw new IllegalStateException ("trying to attach window when one" |
| 184 | + " already exists"); | 186 | + " already exists"); |
| @@ -187,8 +189,15 @@ public class EmacsActivity extends Activity | |||
| 187 | 189 | ||
| 188 | /* Record and attach the view. */ | 190 | /* Record and attach the view. */ |
| 189 | 191 | ||
| 192 | /* Reset residual LayoutParams that might remain in effect on this | ||
| 193 | window, or some distributions of Android (e.g. Huawei HarmonyOS | ||
| 194 | 4.2) will retain the size of this window as a child frame. */ | ||
| 195 | defaultParams | ||
| 196 | = new FrameLayout.LayoutParams (FrameLayout.LayoutParams.MATCH_PARENT, | ||
| 197 | FrameLayout.LayoutParams.MATCH_PARENT); | ||
| 198 | syncFullscreenWith (child); | ||
| 190 | window = child; | 199 | window = child; |
| 191 | layout.addView (window.view); | 200 | layout.addView (window.view, defaultParams); |
| 192 | child.setConsumer (this); | 201 | child.setConsumer (this); |
| 193 | 202 | ||
| 194 | /* If the window isn't no-focus-on-map, focus its view. */ | 203 | /* If the window isn't no-focus-on-map, focus its view. */ |
diff --git a/java/org/gnu/emacs/EmacsService.java b/java/org/gnu/emacs/EmacsService.java index 04563590dc4..8cdf5011b70 100644 --- a/java/org/gnu/emacs/EmacsService.java +++ b/java/org/gnu/emacs/EmacsService.java | |||
| @@ -937,11 +937,11 @@ public final class EmacsService extends Service | |||
| 937 | } | 937 | } |
| 938 | 938 | ||
| 939 | public void | 939 | public void |
| 940 | updateCursorAnchorInfo (EmacsWindow window, float x, | 940 | updateCursorAnchorInfo (final EmacsWindow window, float x, |
| 941 | float y, float yBaseline, | 941 | float y, float yBaseline, |
| 942 | float yBottom) | 942 | float yBottom) |
| 943 | { | 943 | { |
| 944 | CursorAnchorInfo info; | 944 | final CursorAnchorInfo info; |
| 945 | CursorAnchorInfo.Builder builder; | 945 | CursorAnchorInfo.Builder builder; |
| 946 | Matrix matrix; | 946 | Matrix matrix; |
| 947 | int[] offsets; | 947 | int[] offsets; |
| @@ -963,9 +963,14 @@ public final class EmacsService extends Service | |||
| 963 | Log.d (TAG, ("updateCursorAnchorInfo: " + x + " " + y | 963 | Log.d (TAG, ("updateCursorAnchorInfo: " + x + " " + y |
| 964 | + " " + yBaseline + "-" + yBottom)); | 964 | + " " + yBaseline + "-" + yBottom)); |
| 965 | 965 | ||
| 966 | icBeginSynchronous (); | 966 | EmacsService.SERVICE.runOnUiThread (new Runnable () { |
| 967 | window.view.imManager.updateCursorAnchorInfo (window.view, info); | 967 | @Override |
| 968 | icEndSynchronous (); | 968 | public void |
| 969 | run () | ||
| 970 | { | ||
| 971 | window.view.imManager.updateCursorAnchorInfo (window.view, info); | ||
| 972 | } | ||
| 973 | }); | ||
| 969 | } | 974 | } |
| 970 | 975 | ||
| 971 | 976 | ||
diff --git a/java/org/gnu/emacs/EmacsView.java b/java/org/gnu/emacs/EmacsView.java index 8af76c73937..5abea711506 100644 --- a/java/org/gnu/emacs/EmacsView.java +++ b/java/org/gnu/emacs/EmacsView.java | |||
| @@ -296,6 +296,9 @@ public final class EmacsView extends ViewGroup | |||
| 296 | && height > MeasureSpec.getSize (heightMeasureSpec)) | 296 | && height > MeasureSpec.getSize (heightMeasureSpec)) |
| 297 | height = MeasureSpec.getSize (heightMeasureSpec); | 297 | height = MeasureSpec.getSize (heightMeasureSpec); |
| 298 | 298 | ||
| 299 | /* This is strictly necessary to propagate layout requests to | ||
| 300 | children. */ | ||
| 301 | this.measureChildren (widthMeasureSpec, heightMeasureSpec); | ||
| 299 | super.setMeasuredDimension (width, height); | 302 | super.setMeasuredDimension (width, height); |
| 300 | } | 303 | } |
| 301 | 304 | ||
| @@ -467,9 +470,6 @@ public final class EmacsView extends ViewGroup | |||
| 467 | } | 470 | } |
| 468 | } | 471 | } |
| 469 | 472 | ||
| 470 | /* This method is called from both the UI thread and the Emacs | ||
| 471 | thread. */ | ||
| 472 | |||
| 473 | public void | 473 | public void |
| 474 | swapBuffers () | 474 | swapBuffers () |
| 475 | { | 475 | { |
| @@ -620,8 +620,7 @@ public final class EmacsView extends ViewGroup | |||
| 620 | detachViewFromParent (index); | 620 | detachViewFromParent (index); |
| 621 | 621 | ||
| 622 | /* The view at 0 is the surface view. */ | 622 | /* The view at 0 is the surface view. */ |
| 623 | attachViewToParent (child, 1, | 623 | attachViewToParent (child, 1, child.getLayoutParams ()); |
| 624 | child.getLayoutParams ()); | ||
| 625 | } | 624 | } |
| 626 | } | 625 | } |
| 627 | 626 | ||
diff --git a/java/org/gnu/emacs/EmacsWindow.java b/java/org/gnu/emacs/EmacsWindow.java index 2f4e378fb78..861bcace2ad 100644 --- a/java/org/gnu/emacs/EmacsWindow.java +++ b/java/org/gnu/emacs/EmacsWindow.java | |||
| @@ -50,6 +50,7 @@ import android.view.InputDevice; | |||
| 50 | import android.view.KeyEvent; | 50 | import android.view.KeyEvent; |
| 51 | import android.view.MotionEvent; | 51 | import android.view.MotionEvent; |
| 52 | import android.view.View; | 52 | import android.view.View; |
| 53 | import android.view.ViewGroup; | ||
| 53 | import android.view.ViewManager; | 54 | import android.view.ViewManager; |
| 54 | import android.view.WindowManager; | 55 | import android.view.WindowManager; |
| 55 | 56 | ||
| @@ -331,23 +332,39 @@ public final class EmacsWindow extends EmacsHandleObject | |||
| 331 | { | 332 | { |
| 332 | int rectWidth, rectHeight; | 333 | int rectWidth, rectHeight; |
| 333 | 334 | ||
| 334 | rect.left = left; | 335 | /* If this is an override-redirect window, don't ever modify |
| 335 | rect.top = top; | 336 | rect.left and rect.top, as its WM window will always have been |
| 336 | rect.right = right; | 337 | moved in unison with itself. */ |
| 337 | rect.bottom = bottom; | ||
| 338 | |||
| 339 | rectWidth = right - left; | ||
| 340 | rectHeight = bottom - top; | ||
| 341 | 338 | ||
| 339 | if (overrideRedirect) | ||
| 340 | { | ||
| 341 | rect.right = rect.left + (right - left); | ||
| 342 | rect.bottom = rect.top + (bottom - top); | ||
| 343 | } | ||
| 342 | /* If parent is null, use xPosition and yPosition instead of the | 344 | /* If parent is null, use xPosition and yPosition instead of the |
| 343 | geometry rectangle positions. */ | 345 | geometry rectangle positions. */ |
| 344 | 346 | else if (parent == null) | |
| 345 | if (parent == null) | 347 | { |
| 348 | rect.left = xPosition; | ||
| 349 | rect.top = yPosition; | ||
| 350 | rect.right = rect.left + (right - left); | ||
| 351 | rect.bottom = rect.top + (bottom - top); | ||
| 352 | } | ||
| 353 | /* Otherwise accept the new position offered by the toolkit. FIXME: | ||
| 354 | isn't there a potential race condition here if the toolkit lays | ||
| 355 | out EmacsView after a child frame's rect is set but before it | ||
| 356 | calls onLayout to read the modifies rect? */ | ||
| 357 | else | ||
| 346 | { | 358 | { |
| 347 | left = xPosition; | 359 | rect.left = left; |
| 348 | top = yPosition; | 360 | rect.top = top; |
| 361 | rect.right = right; | ||
| 362 | rect.bottom = bottom; | ||
| 349 | } | 363 | } |
| 350 | 364 | ||
| 365 | rectWidth = right - left; | ||
| 366 | rectHeight = bottom - top; | ||
| 367 | |||
| 351 | return EmacsNative.sendConfigureNotify (this.handle, | 368 | return EmacsNative.sendConfigureNotify (this.handle, |
| 352 | System.currentTimeMillis (), | 369 | System.currentTimeMillis (), |
| 353 | left, top, rectWidth, | 370 | left, top, rectWidth, |
| @@ -1363,6 +1380,11 @@ public final class EmacsWindow extends EmacsHandleObject | |||
| 1363 | EmacsWindowManager manager; | 1380 | EmacsWindowManager manager; |
| 1364 | ViewManager parent; | 1381 | ViewManager parent; |
| 1365 | 1382 | ||
| 1383 | /* Invalidate the focus; this should transfer the input focus | ||
| 1384 | to the next eligible window as this window is no longer | ||
| 1385 | present in parent.children. */ | ||
| 1386 | EmacsActivity.invalidateFocus (7); | ||
| 1387 | |||
| 1366 | /* First, detach this window if necessary. */ | 1388 | /* First, detach this window if necessary. */ |
| 1367 | manager = EmacsWindowManager.MANAGER; | 1389 | manager = EmacsWindowManager.MANAGER; |
| 1368 | manager.detachWindow (EmacsWindow.this); | 1390 | manager.detachWindow (EmacsWindow.this); |
| @@ -1637,6 +1659,18 @@ public final class EmacsWindow extends EmacsHandleObject | |||
| 1637 | array[0] += x; | 1659 | array[0] += x; |
| 1638 | array[1] += y; | 1660 | array[1] += y; |
| 1639 | 1661 | ||
| 1662 | /* In the case of an override redirect window, the WM window's | ||
| 1663 | extents and position match the Emacs window exactly. */ | ||
| 1664 | |||
| 1665 | if (overrideRedirect) | ||
| 1666 | { | ||
| 1667 | synchronized (this) | ||
| 1668 | { | ||
| 1669 | array[0] += rect.left; | ||
| 1670 | array[1] += rect.top; | ||
| 1671 | } | ||
| 1672 | } | ||
| 1673 | |||
| 1640 | /* Return the resulting coordinates. */ | 1674 | /* Return the resulting coordinates. */ |
| 1641 | return array; | 1675 | return array; |
| 1642 | } | 1676 | } |