Update Android port

* INSTALL.android: Describe that apksigner is also required.
* configure.ac: Correctly add cross/Makefile to
SUBDIR_MAKEFILES.
* cross/Makefile.in: (config.status): Depend on
$(top_srcdir)/config.status.
* doc/emacs/input.texi (On-Screen Keyboards): Document how to
quit without a physical keyboard.
* java/org/gnu/emacs/EmacsNative.java (EmacsNative): New
function `quit'.
* java/org/gnu/emacs/EmacsWindow.java (EmacsWindow): New field
`lastVolumeButtonPress'.
(onKeyDown): Quit if necessary.
* m4/ndk-build.m4 (ndk_where_cc): Fix search if CC is not a
single word.
* src/android.c (android_open): Remove unused variable.
(quit): New function.
* src/androidmenu.c (android_process_events_for_menu): Allow
quitting the menu.
* src/xterm.c (handle_one_xevent, x_term_init, syms_of_xterm):
Implement features described above, so they work on free
operating systems.
* src/xterm.h (struct x_display_info): New fields `quit_keysym',
`quit_keysym_time'.
This commit is contained in:
Po Lu 2023-01-26 22:11:04 +08:00
parent 22f7ad1057
commit b0e7ae6d5b
11 changed files with 141 additions and 12 deletions

View file

@ -40,8 +40,8 @@ Replacing the paths in the command line above with:
are building Emacs to run on.
- the path to the directory in the Android SDK containing binaries
such as `aapt' and `d8'. These are used to build the application
package.
such as `aapt', `apksigner', and `d8'. These are used to build
the application package.
After the configuration process completes, you may run:

View file

@ -7411,11 +7411,7 @@ if test -f "$srcdir/$opt_makefile.in"; then
fi
if test "$ANDROID" = "yes"; then
SUBDIR_MAKEFILES="$SUBDIR_MAKEFILES java/Makefile"
fi
if test "$XCOMPILE" = "yes"; then
SUBDIR_MAKEFILES="$SUBDIR_MAKEFILES cross/Makefile"
SUBDIR_MAKEFILES="$SUBDIR_MAKEFILES java/Makefile cross/Makefile"
fi
dnl The admin/ directory used to be excluded from tarfiles.

View file

@ -60,8 +60,9 @@ all: lib/libgnu.a src/libemacs.so src/android-emacs $(LIBSRC_BINARIES)
# This Makefile relies on builddir and top_builddir being relative
# paths in *.android.
# This file is used to trick lib/gnulib.mk, it is not actually useful.
config.status:
# This file is used to tell lib/gnulib.mk when
# $(top_srcdir)/config.status changes.
config.status: $(top_srcdir)/config.status
touch config.status
src/verbose.mk: verbose.mk.android

View file

@ -94,3 +94,15 @@ that the user is about to enter text in to the current buffer.
Emacs also provides a set of functions to show or hide the on-screen
keyboard. For more details, @pxref{On-Screen Keyboards,,, elisp, The
Emacs Lisp Reference Manual}.
@cindex quitting, without a keyboard
Since it may not be possible for Emacs to display the on screen
keyboard when it is executing a command, Emacs implements a feature on
devices with only an on-screen keyboard, by which two rapid clicks of
a hardware button that is always present on the device results in
Emacs quitting. @xref{Quitting}.
@defvar x-quit-keysym
The exact button is used to do this varies by system: on X, it is
defined in the variable @code{x-quit-keysym}, and on Android, it is
always the volume down button.

View file

@ -74,6 +74,10 @@ public static native void initEmacs (String argv[], String dumpFile,
/* Abort and generate a native core dump. */
public static native void emacsAbort ();
/* Set Vquit_flag to t, resulting in Emacs quitting as soon as
possible. */
public static native void quit ();
/* Send an ANDROID_CONFIGURE_NOTIFY event. The values of all the
functions below are the serials of the events sent. */
public static native long sendConfigureNotify (short window, long time,

View file

@ -124,6 +124,10 @@ private class Coordinate
there is no such window manager. */
private WindowManager windowManager;
/* The time of the last KEYCODE_VOLUME_DOWN press. This is used to
quit Emacs. */
private long lastVolumeButtonPress;
public
EmacsWindow (short handle, final EmacsWindow parent, int x, int y,
int width, int height, boolean overrideRedirect)
@ -513,6 +517,7 @@ private class Coordinate
onKeyDown (int keyCode, KeyEvent event)
{
int state, state_1;
long time;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2)
state = event.getModifiers ();
@ -544,6 +549,20 @@ private class Coordinate
state, keyCode,
event.getUnicodeChar (state_1));
lastModifiers = state;
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)
{
/* Check if this volume down press should quit Emacs.
Most Android devices have no physical keyboard, so it
is unreasonably hard to press C-g. */
time = event.getEventTime ();
if (lastVolumeButtonPress - time < 350)
EmacsNative.quit ();
lastVolumeButtonPress = time;
}
}
public void

View file

@ -166,7 +166,7 @@ that could not be found in the list of directories specified in \
}
# Look for a suitable ar in the same directory as the C compiler.
ndk_where_cc=$(which $CC)
ndk_where_cc=$(which $(echo "$CC" | awk -- "{ print \[$]1 }"))
ndk_ar_search_path=$PATH
# First, try to find $host_alias-ar in PATH.

View file

@ -1228,7 +1228,7 @@ android_open (const char *filename, int oflag, int mode)
{
const char *name;
AAsset *asset;
int fd, oldfd;
int fd;
off_t out_start, out_length;
if (asset_manager && (name = android_get_asset_name (filename)))
@ -1889,6 +1889,12 @@ NATIVE_NAME (emacsAbort) (JNIEnv *env, jobject object)
emacs_abort ();
}
extern JNIEXPORT void JNICALL
NATIVE_NAME (quit) (JNIEnv *env, jobject object)
{
Vquit_flag = Qt;
}
extern JNIEXPORT jlong JNICALL
NATIVE_NAME (sendConfigureNotify) (JNIEnv *env, jobject object,
jshort window, jlong time,

View file

@ -187,6 +187,12 @@ android_process_events_for_menu (int *id)
/* Process pending signals. */
process_pending_signals ();
/* Maybe quit. This is important because the framework (on
Android 4.0.3) can sometimes fail to deliver context menu
closed events if a submenu was opened, and the user still
needs to be able to quit. */
maybe_quit ();
}
/* Restore the input block. */

View file

@ -20103,6 +20103,24 @@ handle_one_xevent (struct x_display_info *dpyinfo,
}
#endif
/* See if keysym should make Emacs quit. */
if (keysym == dpyinfo->quit_keysym
&& (xkey.time - dpyinfo->quit_keysym_time
<= 350))
{
Vquit_flag = Qt;
goto done_keysym;
}
if (keysym == dpyinfo->quit_keysym)
{
/* Otherwise, set the last time that keysym was
pressed. */
dpyinfo->quit_keysym_time = xkey.time;
goto done_keysym;
}
/* If not using XIM/XIC, and a compose sequence is in progress,
we break here. Otherwise, chars_matched is always 0. */
if (compose_status.chars_matched > 0 && nbytes == 0)
@ -23851,6 +23869,24 @@ handle_one_xevent (struct x_display_info *dpyinfo,
}
#endif
/* See if keysym should make Emacs quit. */
if (keysym == dpyinfo->quit_keysym
&& (xev->time - dpyinfo->quit_keysym_time
<= 350))
{
Vquit_flag = Qt;
goto xi_done_keysym;
}
if (keysym == dpyinfo->quit_keysym)
{
/* Otherwise, set the last time that keysym was
pressed. */
dpyinfo->quit_keysym_time = xev->time;
goto xi_done_keysym;
}
/* First deal with keysyms which have defined
translations to characters. */
if (keysym >= 32 && keysym < 128)
@ -29855,6 +29891,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
struct terminal *terminal;
struct x_display_info *dpyinfo;
XrmDatabase xrdb;
Lisp_Object tem, quit_keysym;
#ifdef USE_XCB
xcb_connection_t *xcb_conn;
#endif
@ -29865,7 +29902,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
GdkScreen *gscr;
#endif
#ifdef HAVE_XFIXES
Lisp_Object tem, lisp_name;
Lisp_Object lisp_name;
int num_fast_selections;
Atom selection_name;
#ifdef USE_XCB
@ -30142,6 +30179,28 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
terminal->kboard->reference_count++;
}
/* Now look through Vx_quit_keysym for the quit keysym associated
with this display. */
tem = Vx_quit_keysym;
FOR_EACH_TAIL_SAFE (tem)
{
quit_keysym = XCAR (tem);
/* Check if its car is a string and its cdr a valid keysym.
Skip if it is not. */
if (!CONSP (quit_keysym) || !FIXNUMP (XCDR (quit_keysym))
|| !STRINGP (XCAR (quit_keysym)))
continue;
/* Check if this is the keysym to be used. */
if (strcmp (SSDATA (XCAR (quit_keysym)), ServerVendor (dpy)))
continue;
dpyinfo->quit_keysym = XFIXNUM (XCDR (quit_keysym));
}
/* Put this display on the chain. */
dpyinfo->next = x_display_list;
x_display_list = dpyinfo;
@ -32200,4 +32259,23 @@ frame placement via frame parameters, `set-frame-position', and
`set-frame-size', along with the actual state of a frame after
`x_make_frame_invisible'. */);
Vx_lax_frame_positioning = Qnil;
DEFVAR_LISP ("x-quit-keysym", Vx_quit_keysym,
doc: /* Keysyms which will cause Emacs to quit if rapidly pressed twice.
This is used to support quitting on devices that do not have any kind
of physical keyboard, or where the physical keyboard is incapable of
entering `C-g'. It defaults to `XF86XK_AudioLowerVolume' on XFree86
and X.Org servers, and is unset.
The value is an alist associating between strings, describing X server
vendor names, and a single number describing the keysym to use. The
keysym to use for each display connection is determined upon
connection setup, and does not reflect further changes to this
variable. */);
Vx_quit_keysym
= list2 (Fcons (build_string ("The X.Org Foundation"),
make_int (269025041)),
Fcons (build_string ("The XFree86 Project, Inc."),
make_int (269025041)));
}

View file

@ -920,6 +920,13 @@ struct x_display_info
server_time_monotonic_p will be true). */
int_fast64_t server_time_offset;
#endif
/* Keysym that will cause Emacs to quit if pressed twice within 150
ms. */
KeySym quit_keysym;
/* The last time that keysym was pressed. */
Time quit_keysym_time;
};
#ifdef HAVE_X_I18N