[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
feature/android 46fd03a4961 1/2: Merge remote-tracking branch 'origin/ma
From: |
Po Lu |
Subject: |
feature/android 46fd03a4961 1/2: Merge remote-tracking branch 'origin/master' into feature/android |
Date: |
Mon, 17 Jul 2023 22:13:14 -0400 (EDT) |
branch: feature/android
commit 46fd03a49617066fca87000378771caedfd150f3
Merge: 324d66e3901 9ad601e7d76
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>
Merge remote-tracking branch 'origin/master' into feature/android
---
doc/lispref/commands.texi | 7 +++-
etc/NEWS | 6 ++++
lisp/vc/vc.el | 17 ++-------
src/keyboard.c | 20 ++++++++++-
src/termhooks.h | 6 +++-
src/xfns.c | 1 +
src/xterm.c | 92 ++++++++++++++++++++++++++++++++++++++---------
src/xterm.h | 62 +++++++++++++++++++++++++++++---
8 files changed, 172 insertions(+), 39 deletions(-)
diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi
index bcba3fe4026..ffb01254fc9 100644
--- a/doc/lispref/commands.texi
+++ b/doc/lispref/commands.texi
@@ -2022,11 +2022,16 @@ position. @var{points} is a list of touch points
containing the
up-to-date positions of each touch point currently on the touchscreen.
@cindex @code{touchscreen-end} event
-@item (touchscreen-end @var{point})
+@item (touchscreen-end @var{point} @var{canceled})
This event is sent when @var{point} is no longer present on the
display, because another program took the grab, or because the user
raised the finger from the touchscreen.
+@var{canceled} is non-@code{nil} if the touch sequence has been
+intercepted by another program (such as the window manager), and Emacs
+should undo or avoid any editing commands that would otherwise result
+from the touch sequence.
+
These events also have imaginary prefixes keys added by
@code{read-key-sequence} when they originate on top of a special part
of a frame or window.
diff --git a/etc/NEWS b/etc/NEWS
index d4d9fd37210..76b1cda9e26 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -661,6 +661,12 @@ from within a command.
This user option names directories in which Emacs will treat all
directory-local variables as safe.
++++
+** New parameter to 'touchscreen-end' events.
+CANCEL non-nil establishes that the touch sequence has been
+intercepted by programs such as window managers and should be ignored
+with Emacs.
+
** New variable 'inhibit-auto-fill' to temporarily prevent auto-fill.
+++
diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el
index 6c3094719ed..be7fa46c28e 100644
--- a/lisp/vc/vc.el
+++ b/lisp/vc/vc.el
@@ -1121,19 +1121,8 @@ possible values of STATE are explained in `vc-state',
and MODEL in
the returned list.
BEWARE: this function may change the current buffer."
- (let (new-buf res)
- (with-current-buffer (or (buffer-base-buffer) (current-buffer))
- (setq res
- (vc-deduce-fileset-1 not-state-changing
- allow-unregistered
- state-model-only-files))
- (setq new-buf (current-buffer)))
- (set-buffer new-buf)
- res))
-
-(defun vc-deduce-fileset-1 (not-state-changing
- allow-unregistered
- state-model-only-files)
+ (when (buffer-base-buffer)
+ (set-buffer (buffer-base-buffer)))
(let (backend)
(cond
((derived-mode-p 'vc-dir-mode)
@@ -1158,7 +1147,7 @@ BEWARE: this function may change the current buffer."
(derived-mode-p 'diff-mode)))))
(progn ;FIXME: Why not `with-current-buffer'? --Stef.
(set-buffer vc-parent-buffer)
- (vc-deduce-fileset-1 not-state-changing allow-unregistered
state-model-only-files)))
+ (vc-deduce-fileset not-state-changing allow-unregistered
state-model-only-files)))
((and (not buffer-file-name)
(setq backend (vc-responsible-backend default-directory)))
(list backend nil))
diff --git a/src/keyboard.c b/src/keyboard.c
index 78105fa9e05..bd7433e584a 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -6557,7 +6557,6 @@ make_lispy_event (struct input_event *event)
}
case TOUCHSCREEN_BEGIN_EVENT:
- case TOUCHSCREEN_END_EVENT:
{
Lisp_Object x, y, id, position;
struct frame *f;
@@ -6684,6 +6683,25 @@ make_lispy_event (struct input_event *event)
Fcons (id, position));
}
+ case TOUCHSCREEN_END_EVENT:
+ {
+ Lisp_Object x, y, id, position;
+ struct frame *f = XFRAME (event->frame_or_window);
+
+ id = event->arg;
+ x = event->x;
+ y = event->y;
+
+ position = make_lispy_position (f, x, y, event->timestamp);
+
+ return list3 (((event->kind
+ == TOUCHSCREEN_BEGIN_EVENT)
+ ? Qtouchscreen_begin
+ : Qtouchscreen_end),
+ Fcons (id, position),
+ event->modifiers ? Qt : Qnil);
+ }
+
case PINCH_EVENT:
{
Lisp_Object x, y, position;
diff --git a/src/termhooks.h b/src/termhooks.h
index 99f27cd668e..d978819aeca 100644
--- a/src/termhooks.h
+++ b/src/termhooks.h
@@ -308,7 +308,11 @@ enum event_kind
In TOUCHSCREEN_BEGIN_EVENT and TOUCHSCREEN_END_EVENT, ARG is the
unique ID of the touchpoint, and X and Y are the frame-relative
- positions of the touchpoint. */
+ positions of the touchpoint.
+
+ In TOUCHSCREEN_END_EVENT, non-0 modifiers means that the
+ touchpoint has been canceled. (See (elisp)Touchscreen
+ Events.) */
, TOUCHSCREEN_UPDATE_EVENT
, TOUCHSCREEN_BEGIN_EVENT
diff --git a/src/xfns.c b/src/xfns.c
index 704f7a3f892..854a85f5306 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -4107,6 +4107,7 @@ setup_xi_event_mask (struct frame *f)
XISetMask (m, XI_TouchBegin);
XISetMask (m, XI_TouchUpdate);
XISetMask (m, XI_TouchEnd);
+ XISetMask (m, XI_TouchOwnership);
#if defined HAVE_XINPUT2_4 && defined USE_GTK3
if (FRAME_DISPLAY_INFO (f)->xi2_version >= 4)
diff --git a/src/xterm.c b/src/xterm.c
index 75e5b07f2c0..b818609d4b5 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -5742,6 +5742,10 @@ xi_device_from_id (struct x_display_info *dpyinfo, int
deviceid)
#ifdef HAVE_XINPUT2_2
+/* Record a touch sequence with the identifier DETAIL from the given
+ FRAME on the specified DEVICE. Round X and Y and record them as
+ its current position. */
+
static void
xi_link_touch_point (struct xi_device_t *device,
int detail, double x, double y,
@@ -5751,19 +5755,28 @@ xi_link_touch_point (struct xi_device_t *device,
touchpoint = xmalloc (sizeof *touchpoint);
touchpoint->next = device->touchpoints;
- touchpoint->x = x;
- touchpoint->y = y;
+ touchpoint->x = lrint (x);
+ touchpoint->y = lrint (y);
touchpoint->number = detail;
touchpoint->frame = frame;
+ touchpoint->ownership = TOUCH_OWNERSHIP_NONE;
device->touchpoints = touchpoint;
}
-static bool
-xi_unlink_touch_point (int detail,
- struct xi_device_t *device)
+/* Free and remove the touch sequence with the identifier DETAIL.
+ DEVICE is the device in which the touch sequence should be
+ recorded.
+
+ Value is 0 if no touch sequence by that identifier exists inside
+ DEVICE, 1 if a touch sequence has been found but is not owned by
+ Emacs, and 2 otherwise. */
+
+static int
+xi_unlink_touch_point (int detail, struct xi_device_t *device)
{
struct xi_touch_point_t *last, *tem;
+ enum xi_touch_ownership ownership;
for (last = NULL, tem = device->touchpoints; tem;
last = tem, tem = tem->next)
@@ -5775,12 +5788,17 @@ xi_unlink_touch_point (int detail,
else
last->next = tem->next;
+ ownership = tem->ownership;
xfree (tem);
- return true;
+
+ if (ownership == TOUCH_OWNERSHIP_SELF)
+ return 2;
+
+ return 1;
}
}
- return false;
+ return 0;
}
/* Unlink all touch points associated with the frame F.
@@ -5813,6 +5831,10 @@ xi_unlink_touch_points (struct frame *f)
}
}
+/* Return the data associated with a touch sequence DETAIL recorded by
+ `xi_link_touch_point' from DEVICE, or NULL if it can't be
+ found. */
+
static struct xi_touch_point_t *
xi_find_touch_point (struct xi_device_t *device, int detail)
{
@@ -24458,12 +24480,48 @@ handle_one_xevent (struct x_display_info *dpyinfo,
goto XI_OTHER;
}
+ case XI_TouchOwnership:
+ {
+ struct xi_device_t *device;
+ struct xi_touch_point_t *touchpoint;
+ XITouchOwnershipEvent *event;
+
+ /* All grabbing clients have decided to reject ownership
+ of this touch sequence. */
+
+ event = (XITouchOwnershipEvent *) xi_event;
+ device = xi_device_from_id (dpyinfo, event->deviceid);
+
+ if (!device || device->use == XIMasterPointer)
+ goto XI_OTHER;
+
+ touchpoint = xi_find_touch_point (device, event->touchid);
+
+ if (!touchpoint)
+ goto XI_OTHER;
+
+ /* As a result, Emacs should complete whatever editing
+ operations result from this touch sequence. */
+ touchpoint->ownership = TOUCH_OWNERSHIP_SELF;
+ }
+
case XI_TouchUpdate:
{
struct xi_device_t *device, *source;
struct xi_touch_point_t *touchpoint;
Lisp_Object arg = Qnil;
+ /* If flags & TouchPendingEnd, the touch sequence has
+ already ended, but some grabbing clients remain
+ undecided as to whether they will obtain ownership of
+ the touch sequence.
+
+ Wait for them to make their decision, resulting in
+ TouchOwnership and TouchEnd events being sent. */
+
+ if (xev->flags & XITouchPendingEnd)
+ goto XI_OTHER;
+
device = xi_device_from_id (dpyinfo, xev->deviceid);
source = xi_device_from_id (dpyinfo, xev->sourceid);
x_display_set_last_user_time (dpyinfo, xev->time,
@@ -24475,7 +24533,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
detached, and master pointers may also represent
dependent touch devices. */
- if (!device)
+ if (!device || device->use == XIMasterPointer)
goto XI_OTHER;
touchpoint = xi_find_touch_point (device, xev->detail);
@@ -24483,12 +24541,12 @@ handle_one_xevent (struct x_display_info *dpyinfo,
if (!touchpoint
/* Don't send this event if nothing has changed
either. */
- || (touchpoint->x == (int) xev->event_x
- && touchpoint->y == (int) xev->event_y))
+ || (touchpoint->x == lrint (xev->event_x)
+ && touchpoint->y == lrint (xev->event_y)))
goto XI_OTHER;
- touchpoint->x = xev->event_x;
- touchpoint->y = xev->event_y;
+ touchpoint->x = lrint (xev->event_x);
+ touchpoint->y = lrint (xev->event_y);
f = x_window_to_frame (dpyinfo, xev->event);
@@ -24502,8 +24560,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
touchpoint; touchpoint = touchpoint->next)
{
if (touchpoint->frame == f)
- arg = Fcons (list3i (lrint (touchpoint->x),
- lrint (touchpoint->y),
+ arg = Fcons (list3i (touchpoint->x, touchpoint->y,
lrint (touchpoint->number)),
arg);
}
@@ -24520,7 +24577,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
case XI_TouchEnd:
{
struct xi_device_t *device, *source;
- bool unlinked_p;
+ int state;
device = xi_device_from_id (dpyinfo, xev->deviceid);
source = xi_device_from_id (dpyinfo, xev->sourceid);
@@ -24536,9 +24593,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
if (!device || device->use == XIMasterPointer)
goto XI_OTHER;
- unlinked_p = xi_unlink_touch_point (xev->detail, device);
+ state = xi_unlink_touch_point (xev->detail, device);
- if (unlinked_p)
+ if (state)
{
f = x_window_to_frame (dpyinfo, xev->event);
@@ -24546,6 +24603,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
{
inev.ie.kind = TOUCHSCREEN_END_EVENT;
inev.ie.timestamp = xev->time;
+ inev.ie.modifiers = state != 2;
XSETFRAME (inev.ie.frame_or_window, f);
XSETINT (inev.ie.x, lrint (xev->event_x));
diff --git a/src/xterm.h b/src/xterm.h
index e7171ba072f..cb477645bfa 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -255,19 +255,71 @@ struct xi_scroll_valuator_t
#ifdef HAVE_XINPUT2_2
+/* Enum describing the ownership of a touch point.
+
+ The input extension allows other clients to intercept touch
+ sequences destined for a client window through passively grabbing
+ for touch events on a parent window.
+
+ When a passive touch grab for an XI_TouchBegin event activates, one
+ grabbing client is designated the ``owner'' of the touch sequence
+ started by the grabbed event. Touch events are then delivered to
+ both the grabbing client and other clients that have selected for
+ touch events on the subwindow.
+
+ The X server will not deliver TouchEnd events to clients other than
+ the owner until one grabbing client decides to take over processing
+ the touch event sequence, or no more grabbing clients remain.
+ Instead, a TouchUpdate event with the TouchPendingEnd flag is sent,
+ and the TouchEnd event is postponed until the decision is made and
+ all XI_TouchOwnership events are sent.
+
+ If the owner decides to take over processing the touch sequence, an
+ XI_TouchEnd event is delivered to all other clients receiving
+ events for the current touch sequence, who are then expected to
+ cancel or undo any actions which have taken place in reaction to
+ events from that sequence.
+
+ If the owner decides to relinquish ownership over the touch
+ sequence, the X server looks for another grabbing client, and
+ transfers touch ownership to that client instead. Nothing changes
+ from the perspective of clients who have merely selected for events
+ from the subwindow, while an XI_TouchEnd event is delivered to the
+ old owner, and an XI_TouchOwnership event is delivered to the new
+ owner.
+
+ If all grabbing clients reject ownership over the touch sequence,
+ the X server delivers an XI_TouchOwnership event to the client that
+ has selected for touch events on the subwindow, the only client
+ that will receive events for this touch sequence from this time
+ forward. */
+
+enum xi_touch_ownership
+ {
+ /* Emacs doesn't own this touch sequence. */
+ TOUCH_OWNERSHIP_NONE,
+
+ /* Emacs owns this touch sequence. */
+ TOUCH_OWNERSHIP_SELF,
+ };
+
struct xi_touch_point_t
{
- /* The next touch point in this list. */
- struct xi_touch_point_t *next;
-
/* The touchpoint detail. */
int number;
- /* The last known X and Y position of the touchpoint. */
- double x, y;
+ /* Whether or not Emacs has ``exclusive'' access to this touch
+ point. */
+ enum xi_touch_ownership ownership;
+
+ /* The last known rounded X and Y positions of the touchpoint. */
+ int x, y;
/* The frame associated with this touch point. */
struct frame *frame;
+
+ /* The next touch point in this list. */
+ struct xi_touch_point_t *next;
};
#endif