From: Po Lu Date: Wed, 8 Feb 2023 14:40:10 +0000 (+0800) Subject: Update Android port X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=0bd4b7fdab2fdf437c4a759d53dfdc9f667aefb1;p=emacs.git Update Android port * 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. --- diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi index 497715bdb19..6ffefe8184f 100644 --- a/doc/lispref/frames.texi +++ b/doc/lispref/frames.texi @@ -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. diff --git a/java/org/gnu/emacs/EmacsSurfaceView.java b/java/org/gnu/emacs/EmacsSurfaceView.java index 2fe9e103b2b..f6cb77bb2b8 100644 --- a/java/org/gnu/emacs/EmacsSurfaceView.java +++ b/java/org/gnu/emacs/EmacsSurfaceView.java @@ -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 diff --git a/java/org/gnu/emacs/EmacsView.java b/java/org/gnu/emacs/EmacsView.java index 873124c86d1..fac11870ebf 100644 --- a/java/org/gnu/emacs/EmacsView.java +++ b/java/org/gnu/emacs/EmacsView.java @@ -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) diff --git a/lisp/frame.el b/lisp/frame.el index a88af24a152..d925a87153c 100644 --- a/lisp/frame.el +++ b/lisp/frame.el @@ -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)))) ;;;; Frame geometry values diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index 3b110e8416f..8c1a0d4b21c 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -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) diff --git a/lisp/touch-screen.el b/lisp/touch-screen.el index 8c4a73f326d..01e56f1d499 100644 --- a/lisp/touch-screen.el +++ b/lisp/touch-screen.el @@ -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)))))))))) diff --git a/src/android.c b/src/android.c index a0e64471a05..ebd374addbf 100644 --- a/src/android.c +++ b/src/android.c @@ -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 (); -} - /* When calling the system's faccessat, make sure to clear the flag diff --git a/src/android.h b/src/android.h index da5c4379800..9006f5f34c5 100644 --- a/src/android.h +++ b/src/android.h @@ -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); diff --git a/src/androidterm.c b/src/androidterm.c index d5dafe9b0d7..4aee1a90b68 100644 --- a/src/androidterm.c +++ b/src/androidterm.c @@ -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 (); diff --git a/src/androidterm.h b/src/androidterm.h index 8cc31f1ab57..ac845187a66 100644 --- a/src/androidterm.h +++ b/src/androidterm.h @@ -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