From: Po Lu Date: Wed, 12 Jul 2023 01:45:58 +0000 (+0800) Subject: Update Android port X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=c8c2bec5f8e4964f23345e1150a7ab85003e688b;p=emacs.git Update Android port * java/org/gnu/emacs/EmacsWindow.java (whatButtonWasIt): Handle back and forward buttons along with styluses. * src/doc.c (close_file_unwind_android_fd): New function. (get_doc_string, Fsnarf_documentation): Don't create a temporary fd if it can be avoided. --- diff --git a/java/org/gnu/emacs/EmacsWindow.java b/java/org/gnu/emacs/EmacsWindow.java index 6816f3e8e71..5e45275631b 100644 --- a/java/org/gnu/emacs/EmacsWindow.java +++ b/java/org/gnu/emacs/EmacsWindow.java @@ -700,29 +700,36 @@ public final class EmacsWindow extends EmacsHandleObject Android does not conceptually distinguish between mouse events (those coming from a device whose movement affects the on-screen - pointer image) and touch screen events. When a touch, click, or - pointer motion takes place, several kinds of event can be sent: + pointer image) and touch screen events. Each click or touch + starts a single pointer gesture sequence, and subsequent motion + of the device will result in updates being reported relative to + that sequence until the mouse button or touch is released. + + When a touch, click, or pointer motion takes place, several kinds + of event can be sent: ACTION_DOWN or ACTION_POINTER_DOWN is sent with a new coordinate - and an associated ``pointer ID'' identifying the event when a - click or touch takes place. Emacs is responsible for recording - both the position of this click for the purpose of determining - future changes to the position of that touch. + and an associated ``pointer ID'' identifying the event and its + gesture sequence when a click or touch takes place. Emacs is + responsible for recording both the position and pointer ID of + this click for the purpose of determining future changes to its + position. ACTION_UP or ACTION_POINTER_UP is sent with a pointer ID when the click associated with a previous ACTION_DOWN event is released. ACTION_CANCEL (or ACTION_POINTER_UP with FLAG_CANCELED) is sent if a similar situation transpires: the window system has chosen - to grab of the click, and future movement will no longer be - reported to Emacs. + to grab the click, and future changes to its position will no + longer be reported to Emacs. ACTION_MOVE is sent if a coordinate tied to a click that has not been released changes. Emacs processes this event by comparing each of the coordinates within the event with its recollection of those contained within prior ACTION_DOWN and ACTION_MOVE events; - the pointer ID of the difference is then reported within a touch - or pointer motion event along with its new position. + the pointer ID of the differing coordinate is then reported + within a touch or pointer motion event along with its new + position. The events described above are all sent for both touch and mouse click events. Determining whether an ACTION_DOWN event is @@ -746,7 +753,12 @@ public final class EmacsWindow extends EmacsHandleObject coordinate. ACTION_HOVER_ENTER and ACTION_HOVER_LEAVE are respectively sent - when the mouse pointer enters and leaves a frame. + when the mouse pointer enters and leaves a frame. Moreover, + ACTION_HOVER_LEAVE events are sent immediately before an + ACTION_DOWN event associated with a mouse click. These + extraneous events are distinct in that their button states always + contain an additional button compared to the button state + recorded at the time of the last ACTION_UP event. On Android 6.0 and later, ACTION_BUTTON_PRESS is sent with the coordinate of the mouse pointer if a mouse click occurs, @@ -789,8 +801,25 @@ public final class EmacsWindow extends EmacsHandleObject if ((notIn & MotionEvent.BUTTON_TERTIARY) != 0) return 2; + /* Buttons 4, 5, 6 and 7 are actually scroll wheels under X. + Thus, report additional buttons starting at 8. */ + + if ((notIn & MotionEvent.BUTTON_BACK) != 0) + return 8; + + if ((notIn & MotionEvent.BUTTON_FORWARD) != 0) + return 9; + + /* Report stylus events as touch screen events. */ + + if ((notIn & MotionEvent.BUTTON_STYLUS_PRIMARY) != 0) + return 0; + + if ((notIn & MotionEvent.BUTTON_STYLUS_SECONDARY) != 0) + return 0; + /* Not a real value. */ - return 4; + return 11; } /* Return the mouse button associated with the specified ACTION_DOWN diff --git a/src/doc.c b/src/doc.c index 174341523d7..56991ffcdfe 100644 --- a/src/doc.c +++ b/src/doc.c @@ -37,6 +37,41 @@ along with GNU Emacs. If not, see . */ #include "intervals.h" #include "keymap.h" + + +#if !defined HAVE_ANDROID || defined ANDROID_STUBIFY \ + || (__ANDROID_API__ < 9) +#define doc_fd int +#define doc_fd_p(fd) ((fd) >= 0) +#define doc_open emacs_open +#define doc_close emacs_close +#define doc_read_quit emacs_read_quit +#define doc_lseek lseek +#else /* HAVE_ANDROID && !defined ANDROID_STUBIFY + && __ANDROID_API__ >= 9 */ + +#include "android.h" + +/* Use an Android file descriptor under Android instead, as this + allows loading directly from asset files without loading each asset + into memory and creating a separate file descriptor every time. + + However, lread requires the ability to seek inside asset files, + which is not provided under Android 2.2. So when building for that + particular system, fall back to the usual file descriptor-based + code. */ + +#define doc_fd struct android_fd_or_asset +#define doc_fd_p(fd) ((fd).asset != (void *) -1) +#define doc_open android_open_asset +#define doc_close android_close_asset +#define doc_read_quit android_asset_read_quit +#define doc_lseek android_asset_lseek +#define USE_ANDROID_ASSETS +#endif /* !HAVE_ANDROID || ANDROID_STUBIFY || __ANDROID_API__ < 9 */ + + + /* Buffer used for reading from documentation file. */ static char *get_doc_string_buffer; static ptrdiff_t get_doc_string_buffer_size; @@ -59,6 +94,22 @@ read_bytecode_char (bool unreadflag) return *read_bytecode_pointer++; } +#ifdef USE_ANDROID_ASSETS + +/* Like `close_file_unwind'. However, PTR is a pointer to an Android + file descriptor instead of a system file descriptor. */ + +static void +close_file_unwind_android_fd (void *ptr) +{ + struct android_fd_or_asset *fd; + + fd = ptr; + android_close_asset (*fd); +} + +#endif /* USE_ANDROID_ASSETS */ + /* Extract a doc string from a file. FILEPOS says where to get it. If it is an integer, use that position in the standard DOC file. If it is (FILE . INTEGER), use FILE as the file name @@ -123,8 +174,8 @@ get_doc_string (Lisp_Object filepos, bool unibyte, bool definition) name = SAFE_ALLOCA (docdir_sizemax + SBYTES (file)); lispstpcpy (lispstpcpy (name, docdir), file); - int fd = emacs_open (name, O_RDONLY, 0); - if (fd < 0) + doc_fd fd = doc_open (name, O_RDONLY, 0); + if (!doc_fd_p (fd)) { if (will_dump_p ()) { @@ -132,9 +183,9 @@ get_doc_string (Lisp_Object filepos, bool unibyte, bool definition) So check in ../etc. */ lispstpcpy (stpcpy (name, sibling_etc), file); - fd = emacs_open (name, O_RDONLY, 0); + fd = doc_open (name, O_RDONLY, 0); } - if (fd < 0) + if (!doc_fd_p (fd)) { if (errno != ENOENT && errno != ENOTDIR) report_file_error ("Read error on documentation file", file); @@ -145,14 +196,18 @@ get_doc_string (Lisp_Object filepos, bool unibyte, bool definition) return concat3 (cannot_open, file, quote_nl); } } +#ifndef USE_ANDROID_ASSETS record_unwind_protect_int (close_file_unwind, fd); +#else /* USE_ANDROID_ASSETS */ + record_unwind_protect_ptr (close_file_unwind_android_fd, &fd); +#endif /* !USE_ANDROID_ASSETS */ /* Seek only to beginning of disk block. */ /* Make sure we read at least 1024 bytes before `position' so we can check the leading text for consistency. */ int offset = min (position, max (1024, position % (8 * 1024))); if (TYPE_MAXIMUM (off_t) < position - || lseek (fd, position - offset, 0) < 0) + || doc_lseek (fd, position - offset, 0) < 0) error ("Position %"pI"d out of range in doc string file \"%s\"", position, name); @@ -181,7 +236,7 @@ get_doc_string (Lisp_Object filepos, bool unibyte, bool definition) If we read the same block last time, maybe skip this? */ if (space_left > 1024 * 8) space_left = 1024 * 8; - int nread = emacs_read_quit (fd, p, space_left); + int nread = doc_read_quit (fd, p, space_left); if (nread < 0) report_file_error ("Read error on documentation file", file); p[nread] = 0; @@ -504,7 +559,7 @@ That file is found in `../etc' now; later, when the dumped Emacs is run, the same file name is found in the `doc-directory'. */) (Lisp_Object filename) { - int fd; + doc_fd fd; char buf[1024 + 1]; int filled; EMACS_INT pos; @@ -551,21 +606,25 @@ the same file name is found in the `doc-directory'. */) Vbuild_files = Fpurecopy (Vbuild_files); } - fd = emacs_open (name, O_RDONLY, 0); - if (fd < 0) + fd = doc_open (name, O_RDONLY, 0); + if (!doc_fd_p (fd)) { int open_errno = errno; report_file_errno ("Opening doc string file", build_string (name), open_errno); } +#ifndef USE_ANDROID_ASSETS record_unwind_protect_int (close_file_unwind, fd); +#else /* USE_ANDROID_ASSETS */ + record_unwind_protect_ptr (close_file_unwind_android_fd, &fd); +#endif /* !USE_ANDROID_ASSETS */ Vdoc_file_name = filename; filled = 0; pos = 0; while (true) { if (filled < 512) - filled += emacs_read_quit (fd, &buf[filled], sizeof buf - 1 - filled); + filled += doc_read_quit (fd, &buf[filled], sizeof buf - 1 - filled); if (!filled) break;