Report touch events on MS-Windows
* etc/NEWS: Announce change. * src/w32fns.c (RegisterTouchWindow_fn): New function. (w32_createwindow): Assign a base value for touch event identifiers to the frame, and register for touch input. (w32_wnd_proc): Forward WM_TOUCH/WM_TOUCHMOVE messages to the main thread. (globals_of_w32fns): Load RegisterTouchWindow from user32.dll. * src/w32term.c (w32_read_socket) <WM_TOUCH>: Detect WM_TOUCH events, compare and record their touch points with and into the frame's record of their prior state, and report the same to Lisp. (pfnCloseTouchInputHandle, pfnGetTouchInputInfo): New variables. (w32_initialize): Load the above functions from user32.dll. * src/w32term.h (MAX_TOUCH_POINTS): New definition. (struct w32_output) <touch_ids, touch_x, touch_y, touch_base>: New fields.
This commit is contained in:
parent
dcd95d7a77
commit
5eb729c0b3
4 changed files with 223 additions and 6 deletions
11
etc/NEWS
11
etc/NEWS
|
@ -559,11 +559,12 @@ function call.
|
|||
|
||||
+++
|
||||
** Emacs now has better support for touchscreen devices.
|
||||
On systems that understand them (at present X, Android, and PGTK), many
|
||||
touch screen gestures are now implemented and translated into mouse or
|
||||
gesture events, and support for tapping tool bar buttons and opening
|
||||
menus has been written. Countless packages, such as Dired and Custom
|
||||
have been adjusted to better understand touch screen input.
|
||||
On systems that understand them (at present X, Android, PGTK, and
|
||||
MS-Windows), many touch screen gestures are now implemented and
|
||||
translated into mouse or gesture events, and support for tapping tool
|
||||
bar buttons and opening menus has been written. Countless packages,
|
||||
such as Dired and Custom have been adjusted to better understand touch
|
||||
screen input.
|
||||
|
||||
---
|
||||
** On X, Emacs now supports input methods which perform "string conversion".
|
||||
|
|
36
src/w32fns.c
36
src/w32fns.c
|
@ -216,6 +216,8 @@ typedef BOOL (WINAPI * WTSRegisterSessionNotification_Proc)
|
|||
(HWND hwnd, DWORD dwFlags);
|
||||
typedef BOOL (WINAPI * WTSUnRegisterSessionNotification_Proc) (HWND hwnd);
|
||||
|
||||
typedef BOOL (WINAPI * RegisterTouchWindow_proc) (HWND, ULONG);
|
||||
|
||||
TrackMouseEvent_Proc track_mouse_event_fn = NULL;
|
||||
ImmGetCompositionString_Proc get_composition_string_fn = NULL;
|
||||
ImmGetContext_Proc get_ime_context_fn = NULL;
|
||||
|
@ -234,6 +236,7 @@ SetWindowTheme_Proc SetWindowTheme_fn = NULL;
|
|||
DwmSetWindowAttribute_Proc DwmSetWindowAttribute_fn = NULL;
|
||||
WTSUnRegisterSessionNotification_Proc WTSUnRegisterSessionNotification_fn = NULL;
|
||||
WTSRegisterSessionNotification_Proc WTSRegisterSessionNotification_fn = NULL;
|
||||
RegisterTouchWindow_proc RegisterTouchWindow_fn = NULL;
|
||||
|
||||
extern AppendMenuW_Proc unicode_append_menu;
|
||||
|
||||
|
@ -2455,6 +2458,7 @@ w32_createwindow (struct frame *f, int *coords)
|
|||
RECT rect;
|
||||
int top, left;
|
||||
Lisp_Object border_width = Fcdr (Fassq (Qborder_width, f->param_alist));
|
||||
static EMACS_INT touch_base;
|
||||
|
||||
if (FRAME_PARENT_FRAME (f) && FRAME_W32_P (FRAME_PARENT_FRAME (f)))
|
||||
{
|
||||
|
@ -2517,6 +2521,8 @@ w32_createwindow (struct frame *f, int *coords)
|
|||
|
||||
if (hwnd)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (FRAME_SKIP_TASKBAR (f))
|
||||
SetWindowLong (hwnd, GWL_EXSTYLE,
|
||||
GetWindowLong (hwnd, GWL_EXSTYLE) | WS_EX_NOACTIVATE);
|
||||
|
@ -2545,6 +2551,20 @@ w32_createwindow (struct frame *f, int *coords)
|
|||
parent. */
|
||||
MapWindowPoints (HWND_DESKTOP, parent_hwnd, (LPPOINT) &rect, 2);
|
||||
|
||||
/* Enable touch-screen input. */
|
||||
if (RegisterTouchWindow_fn)
|
||||
(*RegisterTouchWindow_fn) (hwnd, 0);
|
||||
|
||||
/* Reset F's touch point array. */
|
||||
for (i = 0; i < ARRAYELTS (f->output_data.w32->touch_ids); ++i)
|
||||
f->output_data.w32->touch_ids[i] = -1;
|
||||
|
||||
/* Assign an offset for touch points reported to F. */
|
||||
if (FIXNUM_OVERFLOW_P (touch_base + MAX_TOUCH_POINTS - 1))
|
||||
touch_base = 0;
|
||||
f->output_data.w32->touch_base = touch_base;
|
||||
touch_base += MAX_TOUCH_POINTS;
|
||||
|
||||
f->left_pos = rect.left;
|
||||
f->top_pos = rect.top;
|
||||
}
|
||||
|
@ -5370,6 +5390,19 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
|
||||
goto dflt;
|
||||
|
||||
#ifdef WM_TOUCHMOVE
|
||||
case WM_TOUCHMOVE:
|
||||
#else /* not WM_TOUCHMOVE */
|
||||
#ifndef WM_TOUCH
|
||||
#define WM_TOUCH 576
|
||||
#endif /* WM_TOUCH */
|
||||
case WM_TOUCH:
|
||||
#endif /* not WM_TOUCHMOVE */
|
||||
my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
|
||||
/* It is said that DefWindowProc will release the touch
|
||||
information in the event. */
|
||||
return 0;
|
||||
|
||||
#ifdef WINDOWSNT
|
||||
case WM_CREATE:
|
||||
setup_w32_kbdhook (hwnd);
|
||||
|
@ -11405,6 +11438,9 @@ globals_of_w32fns (void)
|
|||
system_parameters_info_w_fn = (SystemParametersInfoW_Proc)
|
||||
get_proc_addr (user32_lib, "SystemParametersInfoW");
|
||||
#endif
|
||||
RegisterTouchWindow_fn
|
||||
= (RegisterTouchWindow_proc) get_proc_addr (user32_lib,
|
||||
"RegisterTouchWindow");
|
||||
|
||||
{
|
||||
HMODULE imm32_lib = GetModuleHandle ("imm32.dll");
|
||||
|
|
170
src/w32term.c
170
src/w32term.c
|
@ -120,6 +120,13 @@ BOOL (WINAPI *pfnSetLayeredWindowAttributes) (HWND, COLORREF, BYTE, DWORD);
|
|||
/* PlgBlt is available since Windows 2000. */
|
||||
BOOL (WINAPI *pfnPlgBlt) (HDC, const POINT *, HDC, int, int, int, int, HBITMAP, int, int);
|
||||
|
||||
/* Functions that extract data from touch-screen events. */
|
||||
typedef BOOL (WINAPI * CloseTouchInputHandle_proc) (HANDLE);
|
||||
typedef BOOL (WINAPI * GetTouchInputInfo_proc) (HANDLE, UINT, PTOUCHINPUT, int);
|
||||
|
||||
CloseTouchInputHandle_proc pfnCloseTouchInputHandle;
|
||||
GetTouchInputInfo_proc pfnGetTouchInputInfo;
|
||||
|
||||
|
||||
#ifndef LWA_ALPHA
|
||||
#define LWA_ALPHA 0x02
|
||||
|
@ -139,6 +146,35 @@ BOOL (WINAPI *pfnPlgBlt) (HDC, const POINT *, HDC, int, int, int, int, HBITMAP,
|
|||
#define SM_CYVIRTUALSCREEN 79
|
||||
#endif
|
||||
|
||||
/* Define required types and constants on systems with older headers
|
||||
lest they be absent. */
|
||||
|
||||
#if _WIN32_WINNT < 0x0601
|
||||
#define TOUCHEVENTF_DOWN 0x0001
|
||||
#define TOUCHEVENTF_MOVE 0x0002
|
||||
#define TOUCHEVENTF_UP 0x0004
|
||||
|
||||
#define TOUCHEVENTMASKF_CONTACTAREA 0x0004
|
||||
#define TOUCHEVENTMASKF_EXTRAINFO 0x0002
|
||||
#define TOUCHEVENTMASKF_TIMEFROMSYSTEM 0x0001
|
||||
|
||||
#define WM_TOUCHMOVE 576
|
||||
|
||||
typedef struct _TOUCHINPUT
|
||||
{
|
||||
LONG x;
|
||||
LONG y;
|
||||
HANDLE hSource;
|
||||
DWORD dwID;
|
||||
DWORD dwFlags;
|
||||
DWORD dwMask;
|
||||
DWORD dwTime;
|
||||
ULONG_PTR dwExtraInfo;
|
||||
DWORD cxContact;
|
||||
DWORD cyContact;
|
||||
} TOUCHINPUT, *PTOUCHINPUT;
|
||||
#endif /* _WIN32_WINNT < 0x0601 */
|
||||
|
||||
/* The handle of the frame that currently owns the system caret. */
|
||||
HWND w32_system_caret_hwnd;
|
||||
int w32_system_caret_height;
|
||||
|
@ -6056,6 +6092,137 @@ w32_read_socket (struct terminal *terminal,
|
|||
break;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* These messages existed in prerelease versions of Windows 7,
|
||||
yet, though superseded by just WM_TOUCHMOVE (renamed
|
||||
WM_TOUCH) in the release, are still defined by MinGW's
|
||||
winuser.h. */
|
||||
case WM_TOUCHDOWN:
|
||||
case WM_TOUCHUP:
|
||||
#endif /* 0 */
|
||||
#ifdef WM_TOUCHMOVE
|
||||
case WM_TOUCHMOVE:
|
||||
#else /* not WM_TOUCHMOVE */
|
||||
case WM_TOUCH:
|
||||
#endif /* not WM_TOUCHMOVE */
|
||||
f = w32_window_to_frame (dpyinfo, msg.msg.hwnd);
|
||||
|
||||
/* WM_TOUCH should never be received when touch input
|
||||
functions are unavailable. */
|
||||
if (!pfnGetTouchInputInfo)
|
||||
break;
|
||||
|
||||
if (f)
|
||||
{
|
||||
TOUCHINPUT points[MAX_TOUCH_POINTS];
|
||||
int i, x;
|
||||
|
||||
if ((*pfnGetTouchInputInfo) ((HANDLE) msg.msg.lParam,
|
||||
MAX_TOUCH_POINTS,
|
||||
points, sizeof (TOUCHINPUT)))
|
||||
{
|
||||
bool movement_p = false;
|
||||
EMACS_INT base = FRAME_OUTPUT_DATA (f)->touch_base;
|
||||
|
||||
/* Iterate over the list of touch points in the
|
||||
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)
|
||||
{
|
||||
if (!points[i].dwID)
|
||||
continue;
|
||||
|
||||
/* Search for a slot in touch_ids that is either
|
||||
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))
|
||||
break;
|
||||
}
|
||||
if (x == MAX_TOUCH_POINTS)
|
||||
continue;
|
||||
|
||||
if (points[i].dwFlags & TOUCHEVENTF_UP)
|
||||
{
|
||||
/* Clear the entry in touch_ids and report the
|
||||
change. Unless, of course, the entry be
|
||||
empty. */
|
||||
if (FRAME_OUTPUT_DATA (f)->touch_ids[x] == -1)
|
||||
continue;
|
||||
FRAME_OUTPUT_DATA (f)->touch_ids[x] = -1;
|
||||
|
||||
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.arg, x + base);
|
||||
kbd_buffer_store_event (&inev);
|
||||
EVENT_INIT (inev);
|
||||
}
|
||||
else if (points[i].dwFlags & TOUCHEVENTF_DOWN)
|
||||
{
|
||||
bool 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;
|
||||
|
||||
if (recorded_p)
|
||||
movement_p = true;
|
||||
else
|
||||
{
|
||||
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.arg, x + base);
|
||||
kbd_buffer_store_event (&inev);
|
||||
EVENT_INIT (inev);
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/* Report updated positions of touchpoints if some
|
||||
changed. */
|
||||
if (movement_p)
|
||||
{
|
||||
Lisp_Object arg;
|
||||
|
||||
inev.kind = TOUCHSCREEN_UPDATE_EVENT;
|
||||
inev.timestamp = msg.msg.time;
|
||||
XSETFRAME (inev.frame_or_window, f);
|
||||
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);
|
||||
|
||||
inev.arg = arg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(*CloseTouchInputHandle) ((HANDLE) msg.msg.lParam);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Check for messages registered at runtime. */
|
||||
if (msg.msg.message == msh_mousewheel)
|
||||
|
@ -7893,12 +8060,13 @@ w32_initialize (void)
|
|||
#define LOAD_PROC(lib, fn) pfn##fn = (void *) GetProcAddress (lib, #fn)
|
||||
|
||||
LOAD_PROC (user_lib, SetLayeredWindowAttributes);
|
||||
LOAD_PROC (user_lib, CloseTouchInputHandle);
|
||||
LOAD_PROC (user_lib, GetTouchInputInfo);
|
||||
|
||||
/* PlgBlt is not available on Windows 9X. */
|
||||
HMODULE hgdi = LoadLibrary ("gdi32.dll");
|
||||
if (hgdi)
|
||||
LOAD_PROC (hgdi, PlgBlt);
|
||||
|
||||
#undef LOAD_PROC
|
||||
|
||||
/* Ensure scrollbar handles are at least 5 pixels. */
|
||||
|
|
|
@ -434,6 +434,18 @@ struct w32_output
|
|||
|
||||
/* Whether or not this frame should be double buffered. */
|
||||
unsigned want_paint_buffer : 1;
|
||||
|
||||
#define MAX_TOUCH_POINTS 10
|
||||
/* Array of dwIDs of presently active touch points, or -1 when
|
||||
unpopulated. */
|
||||
int touch_ids[MAX_TOUCH_POINTS];
|
||||
|
||||
/* X and Y coordinates of active touchpoints. */
|
||||
LONG touch_x[MAX_TOUCH_POINTS], touch_y[MAX_TOUCH_POINTS];
|
||||
|
||||
/* Base value for touch point identifiers registered by this
|
||||
frame. */
|
||||
EMACS_INT touch_base;
|
||||
};
|
||||
|
||||
extern struct w32_output w32term_display;
|
||||
|
|
Loading…
Add table
Reference in a new issue