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
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,
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
#include "intervals.h"
#include "keymap.h"
+\f
+
+#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 */
+
+\f
+
/* Buffer used for reading from documentation file. */
static char *get_doc_string_buffer;
static ptrdiff_t get_doc_string_buffer_size;
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
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 ())
{
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);
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);
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;
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;
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;