]> git.eshelyaron.com Git - emacs.git/commitdiff
Update Android port
authorPo Lu <luangruo@yahoo.com>
Wed, 8 Feb 2023 14:40:10 +0000 (22:40 +0800)
committerPo Lu <luangruo@yahoo.com>
Wed, 8 Feb 2023 14:40:10 +0000 (22:40 +0800)
* doc/lispref/frames.texi (On-Screen Keyboards): Describe return
value of `frame-toggle-on-screen-keyboard'.
* java/org/gnu/emacs/EmacsSurfaceView.java (surfaceChanged)
(surfaceCreated, EmacsSurfaceView): Remove unuseful
synchronization code.  The framework doesn't seem to look at
this at all.

* java/org/gnu/emacs/EmacsView.java (EmacsView):
(onLayout): Lay out the window after children.
(swapBuffers): Properly implement `force'.
(windowUpdated): Delete function.

* lisp/frame.el (frame-toggle-on-screen-keyboard): Return
whether or not the on screen keyboard might've been displayed.

* lisp/minibuffer.el (minibuffer-on-screen-keyboard-timer):
(minibuffer-on-screen-keyboard-displayed):
(minibuffer-setup-on-screen-keyboard):
(minibuffer-exit-on-screen-keyboard): Improve OSK dismissal when
there are consecutive minibuffers.

* lisp/touch-screen.el (touch-screen-window-selection-changed):
New function.
(touch-screen-handle-point-up): Register it as a window
selection changed function.

* src/android.c (struct android_emacs_window)
(android_init_emacs_window): Remove references to
`windowUpdated'.
(android_window_updated): Delete function.
* src/android.h (struct android_output): Remove
`last_configure_serial'.
* src/androidterm.c (handle_one_android_event)
(android_frame_up_to_date):
* src/androidterm.h (struct android_output): Remove frame
synchronization, as that does not work on Android.

doc/lispref/frames.texi
java/org/gnu/emacs/EmacsSurfaceView.java
java/org/gnu/emacs/EmacsView.java
lisp/frame.el
lisp/minibuffer.el
lisp/touch-screen.el
src/android.c
src/android.h
src/androidterm.c
src/androidterm.h

index 497715bdb19777c4dbfc145d6b2d473c89cf5a4b..6ffefe8184fde9c2a26747701201a91dec86e128 100644 (file)
@@ -3828,6 +3828,10 @@ This function displays or hides the on-screen keyboard on behalf of
 the frame @var{frame}.  If @var{hide} is non-@code{nil}, then the
 on-screen keyboard is hidden; otherwise, it is displayed.
 
+It returns whether or not the on screen keyboard @strong{may} have
+been displayed, which should be used to determine whether or not to
+hide the on-screen keyboard later.
+
 This has no effect if the system automatically detects when to display
 the on-screen keyboard, or when it does not provide any on-screen
 keyboard.
index 2fe9e103b2b4f34f5e15ca4d55d27ca3c13e8c03..f6cb77bb2b89936849fc6db740bf9b954dc59c92 100644 (file)
@@ -45,14 +45,11 @@ public class EmacsSurfaceView extends SurfaceView
     surfaceChanged (SurfaceHolder holder, int format,
                    int width, int height)
     {
-      Log.d (TAG, "surfaceChanged: " + view + ", " + view.pendingConfigure);
+      Canvas canvas;
 
-      /* Make sure not to swap buffers if there is pending
-        configuration, because otherwise the redraw callback will not
-        run correctly.  */
+      Log.d (TAG, "surfaceChanged: " + view + ", ");
 
-      if (view.pendingConfigure == 0)
-       view.swapBuffers ();
+      view.swapBuffers (true);
     }
 
     @Override
@@ -67,7 +64,7 @@ public class EmacsSurfaceView extends SurfaceView
 
       /* Drop the lock when doing this, or a deadlock can
         result.  */
-      view.swapBuffers ();
+      view.swapBuffers (true);
     }
 
     @Override
@@ -82,44 +79,6 @@ public class EmacsSurfaceView extends SurfaceView
     }
   }
 
-  /* And this is the callback used on Android 26 and later.  It is
-     used because it can tell the system when drawing completes.  */
-
-  private class Callback2 extends Callback implements SurfaceHolder.Callback2
-  {
-    @Override
-    public void
-    surfaceRedrawNeeded (SurfaceHolder holder)
-    {
-      /* This version is not supported.  */
-      return;
-    }
-
-    @Override
-    public void
-    surfaceRedrawNeededAsync (SurfaceHolder holder,
-                             Runnable drawingFinished)
-    {
-      Runnable old;
-
-      Log.d (TAG, "surfaceRedrawNeededAsync: " + view.pendingConfigure);
-
-      /* The system calls this function when it wants to know whether
-        or not Emacs is still configuring itself in response to a
-        resize.
-
-         If the view did not send an outstanding ConfigureNotify
-         event, then call drawingFinish immediately.  Else, give it to
-         the view to execute after drawing completes.  */
-
-      if (view.pendingConfigure == 0)
-       drawingFinished.run ();
-      else
-       /* And set this runnable to run once drawing completes.  */
-       view.drawingFinished = drawingFinished;
-    }
-  }
-
   public
   EmacsSurfaceView (final EmacsView view)
   {
@@ -128,10 +87,7 @@ public class EmacsSurfaceView extends SurfaceView
     this.surfaceChangeLock = new Object ();
     this.view = view;
 
-    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O)
-      getHolder ().addCallback (new Callback ());
-    else
-      getHolder ().addCallback (new Callback2 ());
+    getHolder ().addCallback (new Callback ());
   }
 
   public boolean
index 873124c86d1dec68a59dd1a4180c2d07e64e5f4e..fac11870ebfa57c09ff3cc2cc16bb22f8d21c27d 100644 (file)
@@ -96,13 +96,6 @@ public class EmacsView extends ViewGroup
   /* The InputMethodManager for this view's context.  */
   private InputMethodManager imManager;
 
-  /* Runnable that will run once drawing completes.  */
-  public Runnable drawingFinished;
-
-  /* Serial of the last ConfigureNotify event sent that Emacs has not
-     yet responded to.  0 if there is no such outstanding event.  */
-  public long pendingConfigure;
-
   /* Whether or not this view is attached to a window.  */
   public boolean isAttachedToWindow;
 
@@ -110,6 +103,14 @@ public class EmacsView extends ViewGroup
      displayed whenever possible.  */
   public boolean isCurrentlyTextEditor;
 
+  /* An empty rectangle.  */
+  public static final Rect emptyRect;
+
+  static
+  {
+    emptyRect = new Rect ();
+  };
+
   public
   EmacsView (EmacsWindow window)
   {
@@ -286,16 +287,10 @@ public class EmacsView extends ViewGroup
     int count, i;
     View child;
     Rect windowRect;
+    int wantedWidth, wantedHeight;
 
     count = getChildCount ();
 
-    if (changed || mustReportLayout)
-      {
-       mustReportLayout = false;
-       pendingConfigure
-         = window.viewLayout (left, top, right, bottom);
-      }
-
     measuredWidth = right - left;
     measuredHeight = bottom - top;
 
@@ -311,8 +306,6 @@ public class EmacsView extends ViewGroup
        Log.d (TAG, "onLayout: " + child);
 
        if (child == surfaceView)
-         /* The child is the surface view, so give it the entire
-            view.  */
          child.layout (0, 0, right - left, bottom - top);
        else if (child.getVisibility () != GONE)
          {
@@ -326,6 +319,14 @@ public class EmacsView extends ViewGroup
                          windowRect.right, windowRect.bottom);
          }
       }
+
+    /* Now report the layout change to the window.  */
+
+    if (changed || mustReportLayout)
+      {
+       mustReportLayout = false;
+       window.viewLayout (left, top, right, bottom);
+      }
   }
 
   public void
@@ -352,7 +353,7 @@ public class EmacsView extends ViewGroup
 
     synchronized (damageRegion)
       {
-       if (damageRegion.isEmpty ())
+       if (!force && damageRegion.isEmpty ())
          return;
 
        bitmap = getBitmap ();
@@ -363,7 +364,10 @@ public class EmacsView extends ViewGroup
 
        synchronized (surfaceView.surfaceChangeLock)
          {
-           damageRect = damageRegion.getBounds ();
+           if (!force)
+             damageRect = damageRegion.getBounds ();
+           else
+             damageRect = emptyRect;
 
            if (!surfaceView.isCreated ())
              return;
@@ -612,24 +616,6 @@ public class EmacsView extends ViewGroup
     isCurrentlyTextEditor = false;
   }
 
-  public void
-  windowUpdated (long serial)
-  {
-    Log.d (TAG, "windowUpdated: serial is " + serial);
-
-    if (pendingConfigure <= serial
-       /* Detect wraparound.  */
-       || pendingConfigure - serial >= 0x7fffffff)
-      {
-       pendingConfigure = 0;
-
-       if (drawingFinished != null)
-         drawingFinished.run ();
-
-       drawingFinished = null;
-      }
-  }
-
   @Override
   public InputConnection
   onCreateInputConnection (EditorInfo info)
index a88af24a1523fa6541eafc29c1408ff8260552c6..d925a87153c82f707bbc898522de5613e4962a06 100644 (file)
@@ -2564,11 +2564,16 @@ On systems with an on-screen keyboard, display the on screen
 keyboard on behalf of the frame FRAME if HIDE is nil.  Else, hide
 the on screen keyboard.
 
+Return whether or not the on screen keyboard may have been
+displayed; that is, return t on systems with an on screen
+keyboard, and nil on those without.
+
 FRAME must already have the input focus for this to work
  reliably."
   (let ((frame-type (framep-on-display frame)))
     (cond ((eq frame-type 'android)
-           (android-toggle-on-screen-keyboard frame hide)))))
+           (android-toggle-on-screen-keyboard frame hide) t)
+          (t nil))))
 
 \f
 ;;;; Frame geometry values
index 3b110e8416fd9d4d6419f3d677690a7976fd6594..8c1a0d4b21c96cb995ec2bf31f5cb91ca23684c1 100644 (file)
@@ -4577,20 +4577,49 @@ is included in the return value."
 ;; Try to display the on screen keyboard whenever entering the
 ;; mini-buffer, and hide it whenever leaving.
 
+(defvar minibuffer-on-screen-keyboard-timer nil
+  "Timer run upon exiting the minibuffer.
+It will hide the on screen keyboard when necessary.")
+
+(defvar minibuffer-on-screen-keyboard-displayed nil
+  "Whether or not the on-screen keyboard has been displayed.
+Set inside `minibuffer-setup-on-screen-keyboard'.")
+
 (defun minibuffer-setup-on-screen-keyboard ()
   "Maybe display the on-screen keyboard in the current frame.
 Display the on-screen keyboard in the current frame if the
 last device to have sent an input event is not a keyboard.
 This is run upon minibuffer setup."
+  ;; Don't hide the on screen keyboard later on.
+  (when minibuffer-on-screen-keyboard-timer
+    (cancel-timer minibuffer-on-screen-keyboard-timer)
+    (setq minibuffer-on-screen-keyboard-timer nil))
+  (setq minibuffer-on-screen-keyboard-displayed nil)
   (when (not (memq (device-class last-event-frame
                                last-event-device)
                    '(keyboard core-keyboard)))
-    (frame-toggle-on-screen-keyboard (selected-frame) nil)))
+    (setq minibuffer-on-screen-keyboard-displayed
+          (frame-toggle-on-screen-keyboard (selected-frame) nil))))
 
 (defun minibuffer-exit-on-screen-keyboard ()
   "Hide the on-screen keyboard if it was displayed.
-This is run upon minibuffer exit."
-  (frame-toggle-on-screen-keyboard (selected-frame) t))
+Hide the on-screen keyboard in a timer set to run in 0.1 seconds.
+It will be cancelled if the minibuffer is displayed again within
+that timeframe.
+
+Do not hide the on screen keyboard inside a recursive edit.
+Likewise, do not hide the on screen keyboard if point in the
+window that will be selected after exiting the minibuffer is not
+on read-only text.
+
+The latter is implemented in `touch-screen.el'."
+  (unless (or (not minibuffer-on-screen-keyboard-displayed)
+              (> (recursion-depth) 1))
+    (when minibuffer-on-screen-keyboard-timer
+      (cancel-timer minibuffer-on-screen-keyboard-timer))
+    (setq minibuffer-on-screen-keyboard-timer
+          (run-with-timer 0.1 nil #'frame-toggle-on-screen-keyboard
+                          (selected-frame) t))))
 
 (add-hook 'minibuffer-setup-hook #'minibuffer-setup-on-screen-keyboard)
 (add-hook 'minibuffer-exit-hook #'minibuffer-exit-on-screen-keyboard)
index 8c4a73f326d5ebdfb23988f7924a724a266e2df5..01e56f1d499ed77d042c7b855dae83daec765335 100644 (file)
@@ -351,6 +351,21 @@ then move point to the position of POINT."
                          (goto-char (1+ (window-end nil t))))
                        (redisplay))))))))))))
 
+(defun touch-screen-window-selection-changed (frame)
+  "Notice that FRAME's selected window has changed.
+If point is now on read only text, hide the on screen keyboard.
+Otherwise, cancel any timer that is supposed to hide the keyboard
+in response to the minibuffer being closed."
+  (with-selected-frame frame
+    (if (or buffer-read-only
+            (get-text-property (point) 'read-only))
+        (frame-toggle-on-screen-keyboard (selected-frame) t)
+      ;; Prevent hiding the minibuffer from hiding the on screen
+      ;; keyboard.
+      (when minibuffer-on-screen-keyboard-timer
+        (cancel-timer minibuffer-on-screen-keyboard-timer)
+        (setq minibuffer-on-screen-keyboard-timer nil)))))
+
 (defun touch-screen-handle-point-up (point)
   "Notice that POINT has been removed from the screen.
 POINT should be the point currently tracked as
@@ -404,7 +419,16 @@ is not read-only."
                  (when (memq command touch-screen-set-point-commands)
                    (if (not (or buffer-read-only
                                 (get-text-property (point) 'read-only)))
-                       (frame-toggle-on-screen-keyboard (selected-frame) nil)
+                       ;; Once the on-screen keyboard has been opened,
+                       ;; add `touch-screen-window-selection-changed'
+                       ;; as a window selection change function This
+                       ;; allows the on screen keyboard to be hidden
+                       ;; if the selected window's point becomes read
+                       ;; only at some point in the future.
+                       (progn
+                         (add-hook 'window-selection-change-functions
+                                   #'touch-screen-window-selection-changed)
+                         (frame-toggle-on-screen-keyboard (selected-frame) nil))
                      ;; Otherwise, hide the on screen keyboard now.
                      (frame-toggle-on-screen-keyboard (selected-frame) t))))))))))
 
index a0e64471a053311c3345aeee73ad7d26c627a8a5..ebd374addbf8da5721a52d7de6662a2ffd3147e9 100644 (file)
@@ -125,7 +125,6 @@ struct android_emacs_window
   jclass class;
   jmethodID swap_buffers;
   jmethodID toggle_on_screen_keyboard;
-  jmethodID window_updated;
 };
 
 /* The API level of the current device.  */
@@ -1830,7 +1829,6 @@ android_init_emacs_window (void)
   FIND_METHOD (swap_buffers, "swapBuffers", "()V");
   FIND_METHOD (toggle_on_screen_keyboard,
               "toggleOnScreenKeyboard", "(Z)V");
-  FIND_METHOD (window_updated, "windowUpdated", "(J)V");
 #undef FIND_METHOD
 }
 
@@ -4325,25 +4323,6 @@ android_toggle_on_screen_keyboard (android_window window, bool show)
   android_exception_check ();
 }
 
-/* Tell the window system that all configure events sent to WINDOW
-   have been fully processed, and that it is now okay to display its
-   new contents.  SERIAL is the serial of the last configure event
-   processed.  */
-
-void
-android_window_updated (android_window window, unsigned long serial)
-{
-  jobject object;
-  jmethodID method;
-
-  object = android_resolve_handle (window, ANDROID_HANDLE_WINDOW);
-  method = window_class.window_updated;
-
-  (*android_java_env)->CallVoidMethod (android_java_env, object,
-                                      method, (jlong) serial);
-  android_exception_check ();
-}
-
 \f
 
 /* When calling the system's faccessat, make sure to clear the flag
index da5c4379800be1abad2294287d3ff00c53a17617..9006f5f34c5cac984ec8d834516fc1ef24e6ed0c 100644 (file)
@@ -88,7 +88,6 @@ extern void android_exception_check (void);
 extern void android_get_keysym_name (int, char *, size_t);
 extern void android_wait_event (void);
 extern void android_toggle_on_screen_keyboard (android_window, bool);
-extern void android_window_updated (android_window, unsigned long);
 extern _Noreturn void android_restart_emacs (void);
 extern int android_get_current_api_level (void);
 
index d5dafe9b0d7f15df42c6c2d8906b7da2c1683c83..4aee1a90b688210bc18b5419aecc0c5f72c8350a 100644 (file)
@@ -591,17 +591,7 @@ handle_one_android_event (struct android_display_info *dpyinfo,
          android_clear_under_internal_border (f);
          SET_FRAME_GARBAGED (f);
          cancel_mouse_face (f);
-
-         /* Now stash the serial of this configure event somewhere,
-            and call android_window_updated with it once the redraw
-            completes.  */
-         FRAME_OUTPUT_DATA (f)->last_configure_serial
-           = configureEvent.xconfigure.serial;
        }
-      else
-       /* Reply to this ConfigureNotify event immediately.  */
-       android_window_updated (FRAME_ANDROID_WINDOW (f),
-                               configureEvent.xconfigure.serial);
 
       goto OTHER;
 
@@ -1352,14 +1342,6 @@ android_frame_up_to_date (struct frame *f)
   /* The frame is now complete, as its contents have been drawn.  */
   FRAME_ANDROID_COMPLETE_P (f) = true;
 
-  /* If there was an outstanding configure event, then tell system
-     that the update has finished and the new contents can now be
-     displayed.  */
-  if (FRAME_OUTPUT_DATA (f)->last_configure_serial)
-    android_window_updated (FRAME_ANDROID_WINDOW (f),
-                           FRAME_OUTPUT_DATA (f)->last_configure_serial);
-  FRAME_OUTPUT_DATA (f)->last_configure_serial = 0;
-
   /* Shrink the scanline buffer used by the font backend.  */
   sfntfont_android_shrink_scanline_buffer ();
   unblock_input ();
index 8cc31f1ab57424c75aa6b042ab4207b03ac938ec..ac845187a665cbacd4434bfaab90b729738ebcc0 100644 (file)
@@ -241,11 +241,6 @@ struct android_output
   /* List of all tools (either styluses or fingers) pressed onto the
      frame.  */
   struct android_touch_point *touch_points;
-
-  /* Event serial of the last ConfigureNotify event received that has
-     not yet been drawn.  This is used to synchronize resize with the
-     window system.  0 if no such outstanding event exists.  */
-  unsigned long last_configure_serial;
 };
 
 enum