From: Po Lu Date: Thu, 26 Jan 2023 14:11:04 +0000 (+0800) Subject: Update Android port X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=b0e7ae6d5b68a56da40256c395141f071172a622;p=emacs.git 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'. --- diff --git a/INSTALL.android b/INSTALL.android index 06211e5ec93..e5d7162140d 100644 --- a/INSTALL.android +++ b/INSTALL.android @@ -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: diff --git a/configure.ac b/configure.ac index 879e4ab74aa..aaee65016b2 100644 --- a/configure.ac +++ b/configure.ac @@ -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. diff --git a/cross/Makefile.in b/cross/Makefile.in index 92f8d068975..a44550c6563 100644 --- a/cross/Makefile.in +++ b/cross/Makefile.in @@ -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 diff --git a/doc/emacs/input.texi b/doc/emacs/input.texi index 1a58d1ca0ac..3894d4872e0 100644 --- a/doc/emacs/input.texi +++ b/doc/emacs/input.texi @@ -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. diff --git a/java/org/gnu/emacs/EmacsNative.java b/java/org/gnu/emacs/EmacsNative.java index 7bf8b5f6081..4e91a7be322 100644 --- a/java/org/gnu/emacs/EmacsNative.java +++ b/java/org/gnu/emacs/EmacsNative.java @@ -74,6 +74,10 @@ public class EmacsNative /* 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, diff --git a/java/org/gnu/emacs/EmacsWindow.java b/java/org/gnu/emacs/EmacsWindow.java index 8511af9193e..39eaf2fff80 100644 --- a/java/org/gnu/emacs/EmacsWindow.java +++ b/java/org/gnu/emacs/EmacsWindow.java @@ -124,6 +124,10 @@ public class EmacsWindow extends EmacsHandleObject 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 @@ public class EmacsWindow extends EmacsHandleObject 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 @@ public class EmacsWindow extends EmacsHandleObject 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 diff --git a/m4/ndk-build.m4 b/m4/ndk-build.m4 index bcfe0fed6fe..0ab6197d735 100644 --- a/m4/ndk-build.m4 +++ b/m4/ndk-build.m4 @@ -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. diff --git a/src/android.c b/src/android.c index 1676cbf9942..379b54a65be 100644 --- a/src/android.c +++ b/src/android.c @@ -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, diff --git a/src/androidmenu.c b/src/androidmenu.c index f65b5d3ffd1..7b27825ad60 100644 --- a/src/androidmenu.c +++ b/src/androidmenu.c @@ -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. */ diff --git a/src/xterm.c b/src/xterm.c index 1325d923be9..eeefed34d4b 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -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))); } diff --git a/src/xterm.h b/src/xterm.h index 28ae00ca190..406a7c5c060 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -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