1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2024-11-25 07:28:20 +00:00

Add support for pinch gestures to the XI2 build

* doc/lispref/commands.texi (Misc Events): Document new event
type `pinch'.
* etc/NEWS: Announce new event `pinch'.
* etc/PROBLEMS: Document problems with mismatched libXi
versions.
* lisp/face-remap.el (text-scale--pinch-start-scale): New
variable.
(text-scale-pinch): New command.
* src/keyboard.c (make_lispy_event): Handle PINCH_EVENTs.
(syms_of_keyboard): New symbol `pinch'.
* src/termhooks.h (enum event_kind): New enum `PINCH_EVENT'.
* src/xfns.c (setup_xi_event_mask): Add pinch events to event
mask if available.
* src/xterm.c (handle_one_xevent): Handle pinch events.
This commit is contained in:
Po Lu 2021-12-26 13:47:23 +08:00
parent 4e2058aec3
commit 101bbd1392
8 changed files with 142 additions and 0 deletions

View File

@ -2085,6 +2085,27 @@ portable code, use the variables @code{mouse-wheel-up-event} and
@code{mouse-wheel-down-event} defined in @file{mwheel.el} to determine
what event types to expect for the mouse wheel.
@cindex @code{pinch} event
@item (pinch @var{position} @var{dx} @var{dy} @var{scale} @var{angle})
This kind of event is generated by the user performing a ``pinch''
gesture with two fingers on a touchpad. @var{position} is a mouse
position list (@pxref{Click Events}) detailing the position of the
mouse cursor when the event occured, @var{dx} is the distance between
the horizontal positions of the fingers since the last event in the
same sequence, @var{dy} is the vertical movement of the fingers since
the last event in the same sequence, @var{scale} is the division of
the current distance between the fingers and the distance at the start
of the sequence, and @var{angle} is the delta in degrees between the
angles of the fingers in this event and the fingers in the last event
of the same sequence.
All arguments after @var{position} are floating point numbers.
This event is usually sent as part of a sequence, which begins with
the user placing two fingers on the touchpad and ends with the user
removing those fingers. @var{dx}, @var{dy}, and @var{angle} will be
@code{0.0} in the first event sent after a sequence begins.
@cindex @code{drag-n-drop} event
@item (drag-n-drop @var{position} @var{files})
This kind of event is generated when a group of files is

View File

@ -312,6 +312,9 @@ effectively dragged.
Customize this option to limit the number of entries in the menu
"Edit->Paste from Kill Menu". The default is 60.
---
** Performing a pinch gesture on a touchpad now increases the text scale.
** show-paren-mode
+++
@ -885,6 +888,11 @@ This allows setting a minimum display width for a region of text.
This event is sent whenever the user's finger moves off the mouse
wheel on some mice, or when the user's finger moves off the touchpad.
+++
** New event type 'pinch'.
This event is sent when a user peforms a two-finger pinch gesture on a
touchpad.
** Keymaps and key definitions
+++

View File

@ -1681,6 +1681,18 @@ This happens on the proprietary X server ASTEC-X when the number of
monitors is changed after the server has started. A workaround is to
restart the X server after the monitor configuration has been changed.
*** Touchpad gestures don't work and emit warning messages.
When pinching or swiping on your touchpad, you might see a warning
message that looks like:
XInputWireToCookie: Unknown generic event. type 28
This happens when your XInput headers support XInput 2.4, but the
actual version of libXi installed does not. The solution is to
upgrade your libXi binaries to libXi 1.8.0 or later, to correspond
with your XInput headers.
* Runtime problems on character terminals
*** With X forwarding, mouse highlighting can make Emacs slow.

View File

@ -390,6 +390,30 @@ a top-level keymap, `text-scale-increase' or
(lambda () (interactive) (text-scale-adjust (abs inc))))))
map))))) ;; )
(defvar-local text-scale--pinch-start-scale 0
"The text scale at the start of a pinch sequence.")
;;;###autoload (define-key global-map [pinch] 'text-scale-pinch)
;;;###autoload
(defun text-scale-pinch (event)
"Adjust the height of the default face by the scale in EVENT."
(interactive "e")
(let ((window (posn-window (nth 1 event)))
(scale (nth 4 event))
(dx (nth 2 event))
(dy (nth 3 event))
(angle (nth 5 event)))
(with-selected-window window
(when (and (zerop dx)
(zerop dy)
(zerop angle)
(equal scale 1.0))
(setq text-scale--pinch-start-scale
(if text-scale-mode text-scale-mode-amount 0)))
(text-scale-set
(+ text-scale--pinch-start-scale
(round (log scale text-scale-mode-step)))))))
;; ----------------------------------------------------------------
;; buffer-face-mode

View File

@ -4466,6 +4466,7 @@ static Lisp_Object func_key_syms;
static Lisp_Object mouse_syms;
static Lisp_Object wheel_syms;
static Lisp_Object drag_n_drop_syms;
static Lisp_Object pinch_syms;
/* This is a list of keysym codes for special "accent" characters.
It parallels lispy_accent_keys. */
@ -6032,6 +6033,22 @@ make_lispy_event (struct input_event *event)
Fcons (id, position));
}
case PINCH_EVENT:
{
Lisp_Object x, y, position;
struct frame *f = XFRAME (event->frame_or_window);
x = event->x;
y = event->y;
position = make_lispy_position (f, x, y, event->timestamp);
return Fcons (modify_event_symbol (0, event->modifiers, Qpinch,
Qnil, (const char *[]) {"pinch"},
&pinch_syms, 1),
Fcons (position, event->arg));
}
case TOUCHSCREEN_UPDATE_EVENT:
{
Lisp_Object x, y, id, position, tem, it, evt;
@ -11970,6 +11987,9 @@ syms_of_keyboard (void)
drag_n_drop_syms = Qnil;
staticpro (&drag_n_drop_syms);
pinch_syms = Qnil;
staticpro (&pinch_syms);
unread_switch_frame = Qnil;
staticpro (&unread_switch_frame);
@ -12309,6 +12329,7 @@ See also `pre-command-hook'. */);
DEFSYM (Qtouchscreen_begin, "touchscreen-begin");
DEFSYM (Qtouchscreen_end, "touchscreen-end");
DEFSYM (Qtouchscreen_update, "touchscreen-update");
DEFSYM (Qpinch, "pinch");
Fset (Qecho_area_clear_hook, Qnil);
DEFVAR_LISP ("lucid-menu-bar-dirty-flag", Vlucid_menu_bar_dirty_flag,

View File

@ -293,6 +293,21 @@ enum event_kind
, TOUCHSCREEN_UPDATE_EVENT
, TOUCHSCREEN_BEGIN_EVENT
, TOUCHSCREEN_END_EVENT
/* In a PINCH_EVENT, X and Y are the position of the pointer
relative to the top-left corner of the frame, and arg is a list
of (DX DY SCALE ANGLE), in which:
- DX and DY are the difference between the positions of the
fingers comprising the current gesture and the last such
gesture in the same sequence.
- SCALE is the division of the current distance between the
fingers and the distance at the start of the gesture.
- DELTA-ANGLE is the delta between the angle of the current
event and the last event in the same sequence, in degrees. A
positive delta represents a change clockwise, and a negative
delta represents a change counter-clockwise. */
, PINCH_EVENT
};
/* Bit width of an enum event_kind tag at the start of structs and unions. */

View File

@ -2961,6 +2961,14 @@ setup_xi_event_mask (struct frame *f)
XISetMask (m, XI_TouchBegin);
XISetMask (m, XI_TouchUpdate);
XISetMask (m, XI_TouchEnd);
#ifdef XI_GesturePinchBegin
if (FRAME_DISPLAY_INFO (f)->xi2_version >= 4)
{
XISetMask (m, XI_GesturePinchBegin);
XISetMask (m, XI_GesturePinchUpdate);
XISetMask (m, XI_GesturePinchEnd);
}
#endif
}
#endif
XISelectEvents (FRAME_X_DISPLAY (f),

View File

@ -11044,6 +11044,39 @@ handle_one_xevent (struct x_display_info *dpyinfo,
goto XI_OTHER;
}
#endif
#ifdef XI_GesturePinchBegin
case XI_GesturePinchBegin:
case XI_GesturePinchUpdate:
{
XIGesturePinchEvent *pev = (XIGesturePinchEvent *) xi_event;
struct xi_device_t *device = xi_device_from_id (dpyinfo, pev->deviceid);
if (!device || !device->master_p)
goto XI_OTHER;
any = x_any_window_to_frame (dpyinfo, pev->event);
if (any)
{
inev.ie.kind = PINCH_EVENT;
inev.ie.modifiers = x_x_to_emacs_modifiers (FRAME_DISPLAY_INFO (any),
pev->mods.effective);
XSETINT (inev.ie.x, lrint (pev->event_x));
XSETINT (inev.ie.y, lrint (pev->event_y));
XSETFRAME (inev.ie.frame_or_window, any);
inev.ie.arg = list4 (make_float (pev->delta_x),
make_float (pev->delta_y),
make_float (pev->scale),
make_float (pev->delta_angle));
}
/* Once again GTK seems to crash when confronted by
events it doesn't understand. */
*finish = X_EVENT_DROP;
goto XI_OTHER;
}
case XI_GesturePinchEnd:
*finish = X_EVENT_DROP;
goto XI_OTHER;
#endif
default:
goto XI_OTHER;