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.
This commit is contained in:
parent
7fb0df0ce2
commit
0bd4b7fdab
10 changed files with 94 additions and 135 deletions
|
@ -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.
|
||||
|
|
|
@ -45,14 +45,11 @@ private class Callback implements SurfaceHolder.Callback
|
|||
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 @@ private class Callback implements SurfaceHolder.Callback
|
|||
|
||||
/* Drop the lock when doing this, or a deadlock can
|
||||
result. */
|
||||
view.swapBuffers ();
|
||||
view.swapBuffers (true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -82,44 +79,6 @@ private class Callback implements SurfaceHolder.Callback
|
|||
}
|
||||
}
|
||||
|
||||
/* 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 @@ private class Callback2 extends Callback implements SurfaceHolder.Callback2
|
|||
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
|
||||
|
|
|
@ -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 @@ else if (MeasureSpec.getMode (heightMeasureSpec) == MeasureSpec.AT_MOST
|
|||
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 @@ else if (MeasureSpec.getMode (heightMeasureSpec) == MeasureSpec.AT_MOST
|
|||
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 @@ else if (child.getVisibility () != GONE)
|
|||
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 @@ else if (child.getVisibility () != GONE)
|
|||
|
||||
synchronized (damageRegion)
|
||||
{
|
||||
if (damageRegion.isEmpty ())
|
||||
if (!force && damageRegion.isEmpty ())
|
||||
return;
|
||||
|
||||
bitmap = getBitmap ();
|
||||
|
@ -363,7 +364,10 @@ else if (child.getVisibility () != GONE)
|
|||
|
||||
synchronized (surfaceView.surfaceChangeLock)
|
||||
{
|
||||
damageRect = damageRegion.getBounds ();
|
||||
if (!force)
|
||||
damageRect = damageRegion.getBounds ();
|
||||
else
|
||||
damageRect = emptyRect;
|
||||
|
||||
if (!surfaceView.isCreated ())
|
||||
return;
|
||||
|
@ -612,24 +616,6 @@ else if (child.getVisibility () != GONE)
|
|||
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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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))))))))))
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue