From: Po Lu Date: Sat, 18 Mar 2023 02:54:26 +0000 (+0800) Subject: Update Android port X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=634e3fcc20ea9fa5b1af59286f4b846a351f52c8;p=emacs.git Update Android port * java/org/gnu/emacs/EmacsView.java (EmacsView) (prepareForLayout): New function. Call this prior to mapping the view. (onGlobalLayout): New function. Register as global layout listener. * java/org/gnu/emacs/EmacsWindow.java (EmacsWindow) (notifyContentRectPosition): New function. Use specified xPosition and yPosition when reporting the offsets of children of the root window. * java/org/gnu/emacs/EmacsWindowAttachmentManager.java (registerWindow): Specify activity launch bounds if necessary. * src/androidterm.c (handle_one_android_event): Send MOVE_FRAME_EVENT where necessary. --- diff --git a/java/org/gnu/emacs/EmacsView.java b/java/org/gnu/emacs/EmacsView.java index 681da98fa16..88d17a255a2 100644 --- a/java/org/gnu/emacs/EmacsView.java +++ b/java/org/gnu/emacs/EmacsView.java @@ -28,6 +28,7 @@ import android.view.View; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.ViewGroup; +import android.view.ViewTreeObserver; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; @@ -51,6 +52,7 @@ import android.util.Log; It is also a ViewGroup, as it also lays out children. */ public final class EmacsView extends ViewGroup + implements ViewTreeObserver.OnGlobalLayoutListener { public static final String TAG = "EmacsView"; @@ -136,6 +138,9 @@ public final class EmacsView extends ViewGroup context = getContext (); tem = context.getSystemService (Context.INPUT_METHOD_SERVICE); imManager = (InputMethodManager) tem; + + /* Add this view as its own global layout listener. */ + getViewTreeObserver ().addOnGlobalLayoutListener (this); } private void @@ -238,6 +243,13 @@ public final class EmacsView extends ViewGroup return canvas; } + public void + prepareForLayout (int wantedWidth, int wantedHeight) + { + measuredWidth = wantedWidth; + measuredHeight = wantedWidth; + } + @Override protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) @@ -562,8 +574,7 @@ public final class EmacsView extends ViewGroup bitmapDirty = true; /* Now expose the view contents again. */ - EmacsNative.sendExpose (this.window.handle, 0, 0, - measuredWidth, measuredHeight); + EmacsNative.sendExpose (this.window.handle, 0, 0, 0, 0); super.onAttachedToWindow (); } @@ -678,4 +689,19 @@ public final class EmacsView extends ViewGroup { return icMode; } + + @Override + public void + onGlobalLayout () + { + int[] locations; + + /* Get the absolute offset of this view and specify its left and + top position in subsequent ConfigureNotify events. */ + + locations = new int[2]; + getLocationInWindow (locations); + window.notifyContentRectPosition (locations[0], + locations[1]); + } }; diff --git a/java/org/gnu/emacs/EmacsWindow.java b/java/org/gnu/emacs/EmacsWindow.java index a8d1beedef7..c14bf16b96e 100644 --- a/java/org/gnu/emacs/EmacsWindow.java +++ b/java/org/gnu/emacs/EmacsWindow.java @@ -133,6 +133,9 @@ public final class EmacsWindow extends EmacsHandleObject creating new bitmaps. */ public volatile int background; + /* The position of this window relative to the root window. */ + public int xPosition, yPosition; + public EmacsWindow (short handle, final EmacsWindow parent, int x, int y, int width, int height, boolean overrideRedirect) @@ -192,18 +195,14 @@ public final class EmacsWindow extends EmacsHandleObject background = pixel; } - public Rect + public synchronized Rect getGeometry () { - synchronized (this) - { - /* Huh, this is it. */ - return rect; - } + return new Rect (rect); } @Override - public void + public synchronized void destroyHandle () throws IllegalStateException { if (parent != null) @@ -258,22 +257,28 @@ public final class EmacsWindow extends EmacsHandleObject return attached; } - public long + public synchronized long viewLayout (int left, int top, int right, int bottom) { int rectWidth, rectHeight; - synchronized (this) - { - rect.left = left; - rect.top = top; - rect.right = right; - rect.bottom = bottom; - } + rect.left = left; + rect.top = top; + rect.right = right; + rect.bottom = bottom; rectWidth = right - left; rectHeight = bottom - top; + /* If parent is null, use xPosition and yPosition instead of the + geometry rectangle positions. */ + + if (parent == null) + { + left = xPosition; + top = yPosition; + } + return EmacsNative.sendConfigureNotify (this.handle, System.currentTimeMillis (), left, top, rectWidth, @@ -283,8 +288,6 @@ public final class EmacsWindow extends EmacsHandleObject public void requestViewLayout () { - /* This is necessary because otherwise subsequent drawing on the - Emacs thread may be lost. */ view.explicitlyDirtyBitmap (); EmacsService.SERVICE.runOnUiThread (new Runnable () { @@ -302,35 +305,29 @@ public final class EmacsWindow extends EmacsHandleObject }); } - public void + public synchronized void resizeWindow (int width, int height) { - synchronized (this) - { - rect.right = rect.left + width; - rect.bottom = rect.top + height; + rect.right = rect.left + width; + rect.bottom = rect.top + height; - requestViewLayout (); - } + requestViewLayout (); } - public void + public synchronized void moveWindow (int x, int y) { int width, height; - synchronized (this) - { - width = rect.width (); - height = rect.height (); + width = rect.width (); + height = rect.height (); - rect.left = x; - rect.top = y; - rect.right = x + width; - rect.bottom = y + height; + rect.left = x; + rect.top = y; + rect.right = x + width; + rect.bottom = y + height; - requestViewLayout (); - } + requestViewLayout (); } private WindowManager.LayoutParams @@ -366,13 +363,17 @@ public final class EmacsWindow extends EmacsHandleObject return EmacsService.SERVICE; } - public void + public synchronized void mapWindow () { + final int width, height; + if (isMapped) return; isMapped = true; + width = rect.width (); + height = rect.height (); if (parent == null) { @@ -424,6 +425,7 @@ public final class EmacsWindow extends EmacsHandleObject /* Attach the view. */ try { + view.prepareForLayout (width, height); windowManager.addView (view, params); /* Record the window manager being used in the @@ -448,10 +450,14 @@ public final class EmacsWindow extends EmacsHandleObject public void run () { + /* Prior to mapping the view, set its measuredWidth and + measuredHeight to some reasonable value, in order to + avoid excessive bitmap dirtying. */ + + view.prepareForLayout (width, height); view.setVisibility (View.VISIBLE); if (!getDontFocusOnMap ()) - /* Eventually this should check no-focus-on-map. */ view.requestFocus (); } }); @@ -512,12 +518,9 @@ public final class EmacsWindow extends EmacsHandleObject public void clearWindow () { - synchronized (this) - { - EmacsService.SERVICE.fillRectangle (this, scratchGC, - 0, 0, rect.width (), - rect.height ()); - } + EmacsService.SERVICE.fillRectangle (this, scratchGC, + 0, 0, rect.width (), + rect.height ()); } public void @@ -1001,7 +1004,7 @@ public final class EmacsWindow extends EmacsHandleObject return false; } - public void + public synchronized void reparentTo (final EmacsWindow otherWindow, int x, int y) { int width, height; @@ -1017,15 +1020,12 @@ public final class EmacsWindow extends EmacsHandleObject parent = otherWindow; /* Move this window to the new location. */ - synchronized (this) - { - width = rect.width (); - height = rect.height (); - rect.left = x; - rect.top = y; - rect.right = x + width; - rect.bottom = y + height; - } + width = rect.width (); + height = rect.height (); + rect.left = x; + rect.top = y; + rect.right = x + width; + rect.bottom = y + height; /* Now do the work necessary on the UI thread to reparent the window. */ @@ -1081,7 +1081,7 @@ public final class EmacsWindow extends EmacsHandleObject }); } - public void + public synchronized void raise () { /* This does nothing here. */ @@ -1103,7 +1103,7 @@ public final class EmacsWindow extends EmacsHandleObject }); } - public void + public synchronized void lower () { /* This does nothing here. */ @@ -1125,17 +1125,15 @@ public final class EmacsWindow extends EmacsHandleObject }); } - public int[] + public synchronized int[] getWindowGeometry () { int[] array; - Rect rect; array = new int[4]; - rect = getGeometry (); - array[0] = rect.left; - array[1] = rect.top; + array[0] = parent != null ? rect.left : xPosition; + array[1] = parent != null ? rect.top : yPosition; array[2] = rect.width (); array[3] = rect.height (); @@ -1272,4 +1270,31 @@ public final class EmacsWindow extends EmacsHandleObject } }); } + + public synchronized void + notifyContentRectPosition (int xPosition, int yPosition) + { + Rect geometry; + + /* Ignore these notifications if not a child of the root + window. */ + if (parent != null) + return; + + /* xPosition and yPosition are the position of this window + relative to the screen. Set them and request a ConfigureNotify + event. */ + + if (this.xPosition != xPosition + || this.yPosition != yPosition) + { + this.xPosition = xPosition; + this.yPosition = yPosition; + + EmacsNative.sendConfigureNotify (this.handle, + System.currentTimeMillis (), + xPosition, yPosition, + rect.width (), rect.height ()); + } + } }; diff --git a/java/org/gnu/emacs/EmacsWindowAttachmentManager.java b/java/org/gnu/emacs/EmacsWindowAttachmentManager.java index c0197ab802c..4fda48616f0 100644 --- a/java/org/gnu/emacs/EmacsWindowAttachmentManager.java +++ b/java/org/gnu/emacs/EmacsWindowAttachmentManager.java @@ -22,7 +22,9 @@ package org.gnu.emacs; import java.util.ArrayList; import java.util.List; +import android.app.ActivityOptions; import android.content.Intent; +import android.os.Build; import android.util.Log; /* Code to paper over the differences in lifecycles between @@ -102,6 +104,7 @@ public final class EmacsWindowAttachmentManager registerWindow (EmacsWindow window) { Intent intent; + ActivityOptions options; Log.d (TAG, "registerWindow (maybe): " + window); @@ -128,7 +131,18 @@ public final class EmacsWindowAttachmentManager intent.addFlags (Intent.FLAG_ACTIVITY_NEW_DOCUMENT | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK); - EmacsService.SERVICE.startActivity (intent); + + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) + EmacsService.SERVICE.startActivity (intent); + else + { + /* Specify the desired window size. */ + options = ActivityOptions.makeBasic (); + options.setLaunchBounds (window.getGeometry ()); + EmacsService.SERVICE.startActivity (intent, + options.toBundle ()); + } + Log.d (TAG, "registerWindow: startActivity"); } diff --git a/src/androidterm.c b/src/androidterm.c index 1cf9bc4afde..825d6da60fa 100644 --- a/src/androidterm.c +++ b/src/androidterm.c @@ -787,6 +787,33 @@ handle_one_android_event (struct android_display_info *dpyinfo, cancel_mouse_face (f); } + /* Now change the left and top position of this window. */ + + { + int old_left = f->left_pos; + int old_top = f->top_pos; + Lisp_Object frame; + + XSETFRAME (frame, f); + + { + android_window root; + unsigned int dummy_uint; + + android_get_geometry (FRAME_ANDROID_WINDOW (f), + &root, &f->left_pos, &f->top_pos, + &dummy_uint, &dummy_uint, + &dummy_uint); + } + + if (!FRAME_TOOLTIP_P (f) + && (old_left != f->left_pos || old_top != f->top_pos)) + { + inev.ie.kind = MOVE_FRAME_EVENT; + XSETFRAME (inev.ie.frame_or_window, f); + } + } + goto OTHER; case ANDROID_KEY_PRESS: @@ -1100,6 +1127,11 @@ handle_one_android_event (struct android_display_info *dpyinfo, if (!FRAME_GARBAGED_P (f)) { + __android_log_print (ANDROID_LOG_VERBOSE, __func__, + "expose: %d %d %d %d\n", + event->xexpose.x, event->xexpose.y, + event->xexpose.width, + event->xexpose.height); expose_frame (f, event->xexpose.x, event->xexpose.y, event->xexpose.width, event->xexpose.height); show_back_buffer (f);