From: Po Lu Date: Wed, 19 Feb 2025 12:40:12 +0000 (+0800) Subject: Fix remaining Android bugs reported over the past months X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=2771b86d68f9ef9db648680fc40bf67680286adc;p=emacs.git 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. (cherry picked from commit ded77feffface0c167edacf0d807273f3d4878db) --- diff --git a/java/org/gnu/emacs/EmacsActivity.java b/java/org/gnu/emacs/EmacsActivity.java index 84d22e16820..439a8defa32 100644 --- a/java/org/gnu/emacs/EmacsActivity.java +++ b/java/org/gnu/emacs/EmacsActivity.java @@ -179,6 +179,8 @@ public class EmacsActivity extends Activity public final void attachWindow (EmacsWindow child) { + FrameLayout.LayoutParams defaultParams; + if (window != null) throw new IllegalStateException ("trying to attach window when one" + " already exists"); @@ -187,8 +189,15 @@ public class EmacsActivity extends Activity /* Record and attach the view. */ + /* Reset residual LayoutParams that might remain in effect on this + window, or some distributions of Android (e.g. Huawei HarmonyOS + 4.2) will retain the size of this window as a child frame. */ + defaultParams + = new FrameLayout.LayoutParams (FrameLayout.LayoutParams.MATCH_PARENT, + FrameLayout.LayoutParams.MATCH_PARENT); + syncFullscreenWith (child); window = child; - layout.addView (window.view); + layout.addView (window.view, defaultParams); child.setConsumer (this); /* 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 5225337a826..babf2626ba5 100644 --- a/java/org/gnu/emacs/EmacsService.java +++ b/java/org/gnu/emacs/EmacsService.java @@ -938,11 +938,11 @@ public final class EmacsService extends Service } public void - updateCursorAnchorInfo (EmacsWindow window, float x, + updateCursorAnchorInfo (final EmacsWindow window, float x, float y, float yBaseline, float yBottom) { - CursorAnchorInfo info; + final CursorAnchorInfo info; CursorAnchorInfo.Builder builder; Matrix matrix; int[] offsets; @@ -964,9 +964,14 @@ public final class EmacsService extends Service Log.d (TAG, ("updateCursorAnchorInfo: " + x + " " + y + " " + yBaseline + "-" + yBottom)); - icBeginSynchronous (); - window.view.imManager.updateCursorAnchorInfo (window.view, info); - icEndSynchronous (); + EmacsService.SERVICE.runOnUiThread (new Runnable () { + @Override + public void + run () + { + window.view.imManager.updateCursorAnchorInfo (window.view, info); + } + }); } 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 && height > MeasureSpec.getSize (heightMeasureSpec)) height = MeasureSpec.getSize (heightMeasureSpec); + /* This is strictly necessary to propagate layout requests to + children. */ + this.measureChildren (widthMeasureSpec, heightMeasureSpec); super.setMeasuredDimension (width, height); } @@ -467,9 +470,6 @@ public final class EmacsView extends ViewGroup } } - /* This method is called from both the UI thread and the Emacs - thread. */ - public void swapBuffers () { @@ -620,8 +620,7 @@ public final class EmacsView extends ViewGroup detachViewFromParent (index); /* The view at 0 is the surface view. */ - attachViewToParent (child, 1, - child.getLayoutParams ()); + attachViewToParent (child, 1, child.getLayoutParams ()); } } diff --git a/java/org/gnu/emacs/EmacsWindow.java b/java/org/gnu/emacs/EmacsWindow.java index 6a4d4cba9b9..801a5ebc96b 100644 --- a/java/org/gnu/emacs/EmacsWindow.java +++ b/java/org/gnu/emacs/EmacsWindow.java @@ -50,6 +50,7 @@ import android.view.InputDevice; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; +import android.view.ViewGroup; import android.view.ViewManager; import android.view.WindowManager; @@ -331,23 +332,39 @@ public final class EmacsWindow extends EmacsHandleObject { int rectWidth, rectHeight; - rect.left = left; - rect.top = top; - rect.right = right; - rect.bottom = bottom; - - rectWidth = right - left; - rectHeight = bottom - top; + /* If this is an override-redirect window, don't ever modify + rect.left and rect.top, as its WM window will always have been + moved in unison with itself. */ + if (overrideRedirect) + { + rect.right = rect.left + (right - left); + rect.bottom = rect.top + (bottom - top); + } /* If parent is null, use xPosition and yPosition instead of the geometry rectangle positions. */ - - if (parent == null) + else if (parent == null) + { + rect.left = xPosition; + rect.top = yPosition; + rect.right = rect.left + (right - left); + rect.bottom = rect.top + (bottom - top); + } + /* Otherwise accept the new position offered by the toolkit. FIXME: + isn't there a potential race condition here if the toolkit lays + out EmacsView after a child frame's rect is set but before it + calls onLayout to read the modifies rect? */ + else { - left = xPosition; - top = yPosition; + rect.left = left; + rect.top = top; + rect.right = right; + rect.bottom = bottom; } + rectWidth = right - left; + rectHeight = bottom - top; + return EmacsNative.sendConfigureNotify (this.handle, System.currentTimeMillis (), left, top, rectWidth, @@ -1363,6 +1380,11 @@ public final class EmacsWindow extends EmacsHandleObject EmacsWindowManager manager; ViewManager parent; + /* Invalidate the focus; this should transfer the input focus + to the next eligible window as this window is no longer + present in parent.children. */ + EmacsActivity.invalidateFocus (7); + /* First, detach this window if necessary. */ manager = EmacsWindowManager.MANAGER; manager.detachWindow (EmacsWindow.this); @@ -1637,6 +1659,18 @@ public final class EmacsWindow extends EmacsHandleObject array[0] += x; array[1] += y; + /* In the case of an override redirect window, the WM window's + extents and position match the Emacs window exactly. */ + + if (overrideRedirect) + { + synchronized (this) + { + array[0] += rect.left; + array[1] += rect.top; + } + } + /* Return the resulting coordinates. */ return array; }