emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

feature/android 634e3fcc20e: Update Android port


From: Po Lu
Subject: feature/android 634e3fcc20e: Update Android port
Date: Fri, 17 Mar 2023 22:54:45 -0400 (EDT)

branch: feature/android
commit 634e3fcc20ea9fa5b1af59286f4b846a351f52c8
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    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.
---
 java/org/gnu/emacs/EmacsView.java                  |  30 ++++-
 java/org/gnu/emacs/EmacsWindow.java                | 145 ++++++++++++---------
 .../gnu/emacs/EmacsWindowAttachmentManager.java    |  16 ++-
 src/androidterm.c                                  |  32 +++++
 4 files changed, 160 insertions(+), 63 deletions(-)

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);



reply via email to

[Prev in Thread] Current Thread [Next in Thread]