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.
This commit is contained in:
Po Lu 2023-07-12 09:45:58 +08:00
parent fe7861f808
commit c8c2bec5f8
2 changed files with 110 additions and 22 deletions

View file

@ -700,29 +700,36 @@ private static class Coordinate
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 @@ private static class Coordinate
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 @@ private static class Coordinate
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

View file

@ -37,6 +37,41 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#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;