Amend last change

* lisp/loadup.el: Load touch-screen.el on MS-Windows.

* src/w32fns.c (Emacs_GESTURECONFIG): New structure.
(SetGestureConfig_fn): New variable.
(w32_createwindow): Disable emulated mouse and gesture events
for the frame's window.
(w32_wnd_proc) <WM_LBUTTONDOWN, WM_RBUTTONDOWN, WM_LBUTTONUP>
<WM_RBUTTONUP>: Ignore mouse events which are marked as emulated
pointer events.
(globals_of_w32fns): Load SetGestureConfig from user32.dll.

* src/w32term.c (w32_read_socket): Correct utilization of
GetTouchInputInfo, coordinate spaces, &c.
This commit is contained in:
Po Lu 2024-06-09 20:40:17 +08:00
parent 5eb729c0b3
commit 588a8439e0
3 changed files with 115 additions and 25 deletions

View file

@ -344,7 +344,8 @@
(when (eq system-type 'windows-nt)
(load "w32-fns")
(load "ls-lisp")
(load "dos-w32"))))
(load "dos-w32"))
(load "touch-screen")))
(if (eq system-type 'ms-dos)
(progn
(load "dos-w32")

View file

@ -218,6 +218,19 @@ typedef BOOL (WINAPI * WTSUnRegisterSessionNotification_Proc) (HWND hwnd);
typedef BOOL (WINAPI * RegisterTouchWindow_proc) (HWND, ULONG);
/* Types for gesture recognition are documented by Microsoft but appear
not to be defined anywhere in MinGW's includes. */
typedef struct Emacs_GESTURECONFIG
{
DWORD dwID;
DWORD dwWant;
DWORD dwBlock;
} Emacs_GESTURECONFIG, *Emacs_PGESTURECONFIG;
typedef BOOL (WINAPI * SetGestureConfig_proc) (HWND, DWORD, UINT,
Emacs_PGESTURECONFIG, UINT);
TrackMouseEvent_Proc track_mouse_event_fn = NULL;
ImmGetCompositionString_Proc get_composition_string_fn = NULL;
ImmGetContext_Proc get_ime_context_fn = NULL;
@ -237,6 +250,7 @@ DwmSetWindowAttribute_Proc DwmSetWindowAttribute_fn = NULL;
WTSUnRegisterSessionNotification_Proc WTSUnRegisterSessionNotification_fn = NULL;
WTSRegisterSessionNotification_Proc WTSRegisterSessionNotification_fn = NULL;
RegisterTouchWindow_proc RegisterTouchWindow_fn = NULL;
SetGestureConfig_proc SetGestureConfig_fn = NULL;
extern AppendMenuW_Proc unicode_append_menu;
@ -2553,7 +2567,20 @@ w32_createwindow (struct frame *f, int *coords)
/* Enable touch-screen input. */
if (RegisterTouchWindow_fn)
(*RegisterTouchWindow_fn) (hwnd, 0);
{
Emacs_GESTURECONFIG cfg;
(*RegisterTouchWindow_fn) (hwnd, 0);
/* Disable Window's emulation of mouse events. */
cfg.dwID = 0;
cfg.dwWant = 0;
#ifndef GC_ALLGESTURES
#define GC_ALLGESTURES 0x00000001
#endif /* GC_ALLGESTURES */
cfg.dwBlock = GC_ALLGESTURES;
(*SetGestureConfig_fn) (hwnd, 0, 1, &cfg, sizeof cfg);
}
/* Reset F's touch point array. */
for (i = 0; i < ARRAYELTS (f->output_data.w32->touch_ids); ++i)
@ -4803,6 +4830,14 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
are used together, but only if user has two button mouse. */
case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN:
/* Ignore mouse events produced by a touch screen. */
#ifndef MOUSEEVENTF_FROMTOUCH
#define MOUSEEVENTF_FROMTOUCH 0xFF515700
#endif /* MOUSEEVENTF_FROMTOUCH */
if (GetMessageExtraInfo () & MOUSEEVENTF_FROMTOUCH)
goto dflt;
if (w32_num_mouse_buttons > 2)
goto handle_plain_button;
@ -4868,6 +4903,13 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
case WM_LBUTTONUP:
case WM_RBUTTONUP:
/* Ignore mouse events produced by a touch screen. */
#ifndef MOUSEEVENTF_FROMTOUCH
#define MOUSEEVENTF_FROMTOUCH 0xFF515700
#endif /* MOUSEEVENTF_FROMTOUCH */
if (GetMessageExtraInfo () & MOUSEEVENTF_FROMTOUCH)
goto dflt;
if (w32_num_mouse_buttons > 2)
goto handle_plain_button;
@ -11441,6 +11483,9 @@ globals_of_w32fns (void)
RegisterTouchWindow_fn
= (RegisterTouchWindow_proc) get_proc_addr (user32_lib,
"RegisterTouchWindow");
SetGestureConfig_fn
= (SetGestureConfig_proc) get_proc_addr (user32_lib,
"SetGestureConfig");
{
HMODULE imm32_lib = GetModuleHandle ("imm32.dll");

View file

@ -6114,11 +6114,13 @@ w32_read_socket (struct terminal *terminal,
if (f)
{
TOUCHINPUT points[MAX_TOUCH_POINTS];
int i, x;
TOUCHINPUT *points;
int i, x, px, py;
POINT pt;
points = alloca (sizeof *points * LOWORD (msg.msg.wParam));
if ((*pfnGetTouchInputInfo) ((HANDLE) msg.msg.lParam,
MAX_TOUCH_POINTS,
LOWORD (msg.msg.wParam),
points, sizeof (TOUCHINPUT)))
{
bool movement_p = false;
@ -6128,7 +6130,7 @@ w32_read_socket (struct terminal *terminal,
structure, and for each, enter or remove
information into and from F->touch_ids, and
generate events correspondingly. */
for (i = 0; i < MAX_TOUCH_POINTS; ++i)
for (i = 0; i < LOWORD (msg.msg.wParam); ++i)
{
if (!points[i].dwID)
continue;
@ -6137,14 +6139,34 @@ w32_read_socket (struct terminal *terminal,
empty or matches dwID. */
for (x = 0; x < MAX_TOUCH_POINTS; x++)
{
if (FRAME_OUTPUT_DATA (f)->touch_ids[x] == -1
|| (FRAME_OUTPUT_DATA (f)->touch_ids[x]
== points[i].dwID))
if (FRAME_OUTPUT_DATA (f)->touch_ids[x]
== points[i].dwID)
break;
}
if (x < MAX_TOUCH_POINTS)
goto touch_located;
for (x = 0; x < MAX_TOUCH_POINTS; x++)
{
if (FRAME_OUTPUT_DATA (f)->touch_ids[x] == -1)
break;
}
if (x == MAX_TOUCH_POINTS)
continue;
touch_located:
/* X and Y are fractional values. */
pt.x = points[i].x / 100;
pt.y = points[i].y / 100;
/* Convert them from screen values to client
values. */
ScreenToClient (msg.msg.hwnd, &pt);
px = pt.x;
py = pt.y;
if (points[i].dwFlags & TOUCHEVENTF_UP)
{
/* Clear the entry in touch_ids and report the
@ -6157,22 +6179,25 @@ w32_read_socket (struct terminal *terminal,
inev.kind = TOUCHSCREEN_END_EVENT;
inev.timestamp = msg.msg.time;
XSETFRAME (inev.frame_or_window, f);
XSETINT (inev.x, points[i].x);
XSETINT (inev.y, points[i].y);
XSETINT (inev.x, px);
XSETINT (inev.y, py);
XSETINT (inev.arg, x + base);
kbd_buffer_store_event (&inev);
EVENT_INIT (inev);
}
else if (points[i].dwFlags & TOUCHEVENTF_DOWN)
{
bool recorded_p
bool recorded_p;
touchscreen_down:
recorded_p
= FRAME_OUTPUT_DATA (f)->touch_ids[x] != -1;
/* Report and record (if not already recorded)
the addition. */
FRAME_OUTPUT_DATA (f)->touch_ids[x] = points[i].dwID;
FRAME_OUTPUT_DATA (f)->touch_x[x] = points[i].x;
FRAME_OUTPUT_DATA (f)->touch_y[x] = points[i].y;
FRAME_OUTPUT_DATA (f)->touch_x[x] = px;
FRAME_OUTPUT_DATA (f)->touch_y[x] = py;
if (recorded_p)
movement_p = true;
@ -6181,8 +6206,8 @@ w32_read_socket (struct terminal *terminal,
inev.kind = TOUCHSCREEN_BEGIN_EVENT;
inev.timestamp = msg.msg.time;
XSETFRAME (inev.frame_or_window, f);
XSETINT (inev.x, points[i].x);
XSETINT (inev.y, points[i].y);
XSETINT (inev.x, px);
XSETINT (inev.y, py);
XSETINT (inev.arg, x + base);
kbd_buffer_store_event (&inev);
EVENT_INIT (inev);
@ -6190,10 +6215,20 @@ w32_read_socket (struct terminal *terminal,
}
else
{
FRAME_OUTPUT_DATA (f)->touch_ids[x] = points[i].dwID;
FRAME_OUTPUT_DATA (f)->touch_x[x] = points[i].x;
FRAME_OUTPUT_DATA (f)->touch_y[x] = points[i].y;
movement_p = true;
bool recorded_p
= FRAME_OUTPUT_DATA (f)->touch_ids[x] != -1;
if (!recorded_p)
goto touchscreen_down;
if (FRAME_OUTPUT_DATA (f)->touch_x[x] != px
|| FRAME_OUTPUT_DATA (f)->touch_y[x] != py)
{
movement_p = true;
FRAME_OUTPUT_DATA (f)->touch_ids[x]
= points[i].dwID;
FRAME_OUTPUT_DATA (f)->touch_x[x] = px;
FRAME_OUTPUT_DATA (f)->touch_y[x] = py;
}
}
}
@ -6209,13 +6244,22 @@ w32_read_socket (struct terminal *terminal,
arg = Qnil;
for (i = 0; i < MAX_TOUCH_POINTS; ++i)
arg
= Fcons (list3i (FRAME_OUTPUT_DATA (f)->touch_x[i],
FRAME_OUTPUT_DATA (f)->touch_y[i],
i + base),
arg);
{
if (FRAME_OUTPUT_DATA (f)->touch_ids[i] == -1)
continue;
arg
= Fcons (list3i (FRAME_OUTPUT_DATA (f)->touch_x[i],
FRAME_OUTPUT_DATA (f)->touch_y[i],
i + base),
arg);
}
inev.arg = arg;
/* Don't generate events if they would be empty. */
if (NILP (arg))
EVENT_INIT (inev);
}
}
}