aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPo Lu2024-06-09 17:44:25 +0800
committerPo Lu2024-06-09 20:40:58 +0800
commit5eb729c0b36a31869cf4928bc7bf5111b6f59ebb (patch)
tree322e1c28ceb9e146c610ca6fc01473d374b9242c /src
parentdcd95d7a77dc1016de72860ecb0623b6377bdc65 (diff)
downloademacs-5eb729c0b36a31869cf4928bc7bf5111b6f59ebb.tar.gz
emacs-5eb729c0b36a31869cf4928bc7bf5111b6f59ebb.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/w32fns.c36
-rw-r--r--src/w32term.c170
-rw-r--r--src/w32term.h12
3 files changed, 217 insertions, 1 deletions
diff --git a/src/w32fns.c b/src/w32fns.c
index 8b61b54bdc5..4437c1fb2b5 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -216,6 +216,8 @@ typedef BOOL (WINAPI * WTSRegisterSessionNotification_Proc)
216 (HWND hwnd, DWORD dwFlags); 216 (HWND hwnd, DWORD dwFlags);
217typedef BOOL (WINAPI * WTSUnRegisterSessionNotification_Proc) (HWND hwnd); 217typedef BOOL (WINAPI * WTSUnRegisterSessionNotification_Proc) (HWND hwnd);
218 218
219typedef BOOL (WINAPI * RegisterTouchWindow_proc) (HWND, ULONG);
220
219TrackMouseEvent_Proc track_mouse_event_fn = NULL; 221TrackMouseEvent_Proc track_mouse_event_fn = NULL;
220ImmGetCompositionString_Proc get_composition_string_fn = NULL; 222ImmGetCompositionString_Proc get_composition_string_fn = NULL;
221ImmGetContext_Proc get_ime_context_fn = NULL; 223ImmGetContext_Proc get_ime_context_fn = NULL;
@@ -234,6 +236,7 @@ SetWindowTheme_Proc SetWindowTheme_fn = NULL;
234DwmSetWindowAttribute_Proc DwmSetWindowAttribute_fn = NULL; 236DwmSetWindowAttribute_Proc DwmSetWindowAttribute_fn = NULL;
235WTSUnRegisterSessionNotification_Proc WTSUnRegisterSessionNotification_fn = NULL; 237WTSUnRegisterSessionNotification_Proc WTSUnRegisterSessionNotification_fn = NULL;
236WTSRegisterSessionNotification_Proc WTSRegisterSessionNotification_fn = NULL; 238WTSRegisterSessionNotification_Proc WTSRegisterSessionNotification_fn = NULL;
239RegisterTouchWindow_proc RegisterTouchWindow_fn = NULL;
237 240
238extern AppendMenuW_Proc unicode_append_menu; 241extern AppendMenuW_Proc unicode_append_menu;
239 242
@@ -2455,6 +2458,7 @@ w32_createwindow (struct frame *f, int *coords)
2455 RECT rect; 2458 RECT rect;
2456 int top, left; 2459 int top, left;
2457 Lisp_Object border_width = Fcdr (Fassq (Qborder_width, f->param_alist)); 2460 Lisp_Object border_width = Fcdr (Fassq (Qborder_width, f->param_alist));
2461 static EMACS_INT touch_base;
2458 2462
2459 if (FRAME_PARENT_FRAME (f) && FRAME_W32_P (FRAME_PARENT_FRAME (f))) 2463 if (FRAME_PARENT_FRAME (f) && FRAME_W32_P (FRAME_PARENT_FRAME (f)))
2460 { 2464 {
@@ -2517,6 +2521,8 @@ w32_createwindow (struct frame *f, int *coords)
2517 2521
2518 if (hwnd) 2522 if (hwnd)
2519 { 2523 {
2524 int i;
2525
2520 if (FRAME_SKIP_TASKBAR (f)) 2526 if (FRAME_SKIP_TASKBAR (f))
2521 SetWindowLong (hwnd, GWL_EXSTYLE, 2527 SetWindowLong (hwnd, GWL_EXSTYLE,
2522 GetWindowLong (hwnd, GWL_EXSTYLE) | WS_EX_NOACTIVATE); 2528 GetWindowLong (hwnd, GWL_EXSTYLE) | WS_EX_NOACTIVATE);
@@ -2545,6 +2551,20 @@ w32_createwindow (struct frame *f, int *coords)
2545 parent. */ 2551 parent. */
2546 MapWindowPoints (HWND_DESKTOP, parent_hwnd, (LPPOINT) &rect, 2); 2552 MapWindowPoints (HWND_DESKTOP, parent_hwnd, (LPPOINT) &rect, 2);
2547 2553
2554 /* Enable touch-screen input. */
2555 if (RegisterTouchWindow_fn)
2556 (*RegisterTouchWindow_fn) (hwnd, 0);
2557
2558 /* Reset F's touch point array. */
2559 for (i = 0; i < ARRAYELTS (f->output_data.w32->touch_ids); ++i)
2560 f->output_data.w32->touch_ids[i] = -1;
2561
2562 /* Assign an offset for touch points reported to F. */
2563 if (FIXNUM_OVERFLOW_P (touch_base + MAX_TOUCH_POINTS - 1))
2564 touch_base = 0;
2565 f->output_data.w32->touch_base = touch_base;
2566 touch_base += MAX_TOUCH_POINTS;
2567
2548 f->left_pos = rect.left; 2568 f->left_pos = rect.left;
2549 f->top_pos = rect.top; 2569 f->top_pos = rect.top;
2550 } 2570 }
@@ -5370,6 +5390,19 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
5370 my_post_msg (&wmsg, hwnd, msg, wParam, lParam); 5390 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
5371 goto dflt; 5391 goto dflt;
5372 5392
5393#ifdef WM_TOUCHMOVE
5394 case WM_TOUCHMOVE:
5395#else /* not WM_TOUCHMOVE */
5396#ifndef WM_TOUCH
5397#define WM_TOUCH 576
5398#endif /* WM_TOUCH */
5399 case WM_TOUCH:
5400#endif /* not WM_TOUCHMOVE */
5401 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
5402 /* It is said that DefWindowProc will release the touch
5403 information in the event. */
5404 return 0;
5405
5373#ifdef WINDOWSNT 5406#ifdef WINDOWSNT
5374 case WM_CREATE: 5407 case WM_CREATE:
5375 setup_w32_kbdhook (hwnd); 5408 setup_w32_kbdhook (hwnd);
@@ -11405,6 +11438,9 @@ globals_of_w32fns (void)
11405 system_parameters_info_w_fn = (SystemParametersInfoW_Proc) 11438 system_parameters_info_w_fn = (SystemParametersInfoW_Proc)
11406 get_proc_addr (user32_lib, "SystemParametersInfoW"); 11439 get_proc_addr (user32_lib, "SystemParametersInfoW");
11407#endif 11440#endif
11441 RegisterTouchWindow_fn
11442 = (RegisterTouchWindow_proc) get_proc_addr (user32_lib,
11443 "RegisterTouchWindow");
11408 11444
11409 { 11445 {
11410 HMODULE imm32_lib = GetModuleHandle ("imm32.dll"); 11446 HMODULE imm32_lib = GetModuleHandle ("imm32.dll");
diff --git a/src/w32term.c b/src/w32term.c
index 3ef6d0f11f1..45f94ab76bd 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -120,6 +120,13 @@ BOOL (WINAPI *pfnSetLayeredWindowAttributes) (HWND, COLORREF, BYTE, DWORD);
120/* PlgBlt is available since Windows 2000. */ 120/* PlgBlt is available since Windows 2000. */
121BOOL (WINAPI *pfnPlgBlt) (HDC, const POINT *, HDC, int, int, int, int, HBITMAP, int, int); 121BOOL (WINAPI *pfnPlgBlt) (HDC, const POINT *, HDC, int, int, int, int, HBITMAP, int, int);
122 122
123/* Functions that extract data from touch-screen events. */
124typedef BOOL (WINAPI * CloseTouchInputHandle_proc) (HANDLE);
125typedef BOOL (WINAPI * GetTouchInputInfo_proc) (HANDLE, UINT, PTOUCHINPUT, int);
126
127CloseTouchInputHandle_proc pfnCloseTouchInputHandle;
128GetTouchInputInfo_proc pfnGetTouchInputInfo;
129
123 130
124#ifndef LWA_ALPHA 131#ifndef LWA_ALPHA
125#define LWA_ALPHA 0x02 132#define LWA_ALPHA 0x02
@@ -139,6 +146,35 @@ BOOL (WINAPI *pfnPlgBlt) (HDC, const POINT *, HDC, int, int, int, int, HBITMAP,
139#define SM_CYVIRTUALSCREEN 79 146#define SM_CYVIRTUALSCREEN 79
140#endif 147#endif
141 148
149/* Define required types and constants on systems with older headers
150 lest they be absent. */
151
152#if _WIN32_WINNT < 0x0601
153#define TOUCHEVENTF_DOWN 0x0001
154#define TOUCHEVENTF_MOVE 0x0002
155#define TOUCHEVENTF_UP 0x0004
156
157#define TOUCHEVENTMASKF_CONTACTAREA 0x0004
158#define TOUCHEVENTMASKF_EXTRAINFO 0x0002
159#define TOUCHEVENTMASKF_TIMEFROMSYSTEM 0x0001
160
161#define WM_TOUCHMOVE 576
162
163typedef struct _TOUCHINPUT
164{
165 LONG x;
166 LONG y;
167 HANDLE hSource;
168 DWORD dwID;
169 DWORD dwFlags;
170 DWORD dwMask;
171 DWORD dwTime;
172 ULONG_PTR dwExtraInfo;
173 DWORD cxContact;
174 DWORD cyContact;
175} TOUCHINPUT, *PTOUCHINPUT;
176#endif /* _WIN32_WINNT < 0x0601 */
177
142/* The handle of the frame that currently owns the system caret. */ 178/* The handle of the frame that currently owns the system caret. */
143HWND w32_system_caret_hwnd; 179HWND w32_system_caret_hwnd;
144int w32_system_caret_height; 180int w32_system_caret_height;
@@ -6056,6 +6092,137 @@ w32_read_socket (struct terminal *terminal,
6056 break; 6092 break;
6057#endif 6093#endif
6058 6094
6095#if 0
6096 /* These messages existed in prerelease versions of Windows 7,
6097 yet, though superseded by just WM_TOUCHMOVE (renamed
6098 WM_TOUCH) in the release, are still defined by MinGW's
6099 winuser.h. */
6100 case WM_TOUCHDOWN:
6101 case WM_TOUCHUP:
6102#endif /* 0 */
6103#ifdef WM_TOUCHMOVE
6104 case WM_TOUCHMOVE:
6105#else /* not WM_TOUCHMOVE */
6106 case WM_TOUCH:
6107#endif /* not WM_TOUCHMOVE */
6108 f = w32_window_to_frame (dpyinfo, msg.msg.hwnd);
6109
6110 /* WM_TOUCH should never be received when touch input
6111 functions are unavailable. */
6112 if (!pfnGetTouchInputInfo)
6113 break;
6114
6115 if (f)
6116 {
6117 TOUCHINPUT points[MAX_TOUCH_POINTS];
6118 int i, x;
6119
6120 if ((*pfnGetTouchInputInfo) ((HANDLE) msg.msg.lParam,
6121 MAX_TOUCH_POINTS,
6122 points, sizeof (TOUCHINPUT)))
6123 {
6124 bool movement_p = false;
6125 EMACS_INT base = FRAME_OUTPUT_DATA (f)->touch_base;
6126
6127 /* Iterate over the list of touch points in the
6128 structure, and for each, enter or remove
6129 information into and from F->touch_ids, and
6130 generate events correspondingly. */
6131 for (i = 0; i < MAX_TOUCH_POINTS; ++i)
6132 {
6133 if (!points[i].dwID)
6134 continue;
6135
6136 /* Search for a slot in touch_ids that is either
6137 empty or matches dwID. */
6138 for (x = 0; x < MAX_TOUCH_POINTS; x++)
6139 {
6140 if (FRAME_OUTPUT_DATA (f)->touch_ids[x] == -1
6141 || (FRAME_OUTPUT_DATA (f)->touch_ids[x]
6142 == points[i].dwID))
6143 break;
6144 }
6145 if (x == MAX_TOUCH_POINTS)
6146 continue;
6147
6148 if (points[i].dwFlags & TOUCHEVENTF_UP)
6149 {
6150 /* Clear the entry in touch_ids and report the
6151 change. Unless, of course, the entry be
6152 empty. */
6153 if (FRAME_OUTPUT_DATA (f)->touch_ids[x] == -1)
6154 continue;
6155 FRAME_OUTPUT_DATA (f)->touch_ids[x] = -1;
6156
6157 inev.kind = TOUCHSCREEN_END_EVENT;
6158 inev.timestamp = msg.msg.time;
6159 XSETFRAME (inev.frame_or_window, f);
6160 XSETINT (inev.x, points[i].x);
6161 XSETINT (inev.y, points[i].y);
6162 XSETINT (inev.arg, x + base);
6163 kbd_buffer_store_event (&inev);
6164 EVENT_INIT (inev);
6165 }
6166 else if (points[i].dwFlags & TOUCHEVENTF_DOWN)
6167 {
6168 bool recorded_p
6169 = FRAME_OUTPUT_DATA (f)->touch_ids[x] != -1;
6170
6171 /* Report and record (if not already recorded)
6172 the addition. */
6173 FRAME_OUTPUT_DATA (f)->touch_ids[x] = points[i].dwID;
6174 FRAME_OUTPUT_DATA (f)->touch_x[x] = points[i].x;
6175 FRAME_OUTPUT_DATA (f)->touch_y[x] = points[i].y;
6176
6177 if (recorded_p)
6178 movement_p = true;
6179 else
6180 {
6181 inev.kind = TOUCHSCREEN_BEGIN_EVENT;
6182 inev.timestamp = msg.msg.time;
6183 XSETFRAME (inev.frame_or_window, f);
6184 XSETINT (inev.x, points[i].x);
6185 XSETINT (inev.y, points[i].y);
6186 XSETINT (inev.arg, x + base);
6187 kbd_buffer_store_event (&inev);
6188 EVENT_INIT (inev);
6189 }
6190 }
6191 else
6192 {
6193 FRAME_OUTPUT_DATA (f)->touch_ids[x] = points[i].dwID;
6194 FRAME_OUTPUT_DATA (f)->touch_x[x] = points[i].x;
6195 FRAME_OUTPUT_DATA (f)->touch_y[x] = points[i].y;
6196 movement_p = true;
6197 }
6198 }
6199
6200 /* Report updated positions of touchpoints if some
6201 changed. */
6202 if (movement_p)
6203 {
6204 Lisp_Object arg;
6205
6206 inev.kind = TOUCHSCREEN_UPDATE_EVENT;
6207 inev.timestamp = msg.msg.time;
6208 XSETFRAME (inev.frame_or_window, f);
6209 arg = Qnil;
6210
6211 for (i = 0; i < MAX_TOUCH_POINTS; ++i)
6212 arg
6213 = Fcons (list3i (FRAME_OUTPUT_DATA (f)->touch_x[i],
6214 FRAME_OUTPUT_DATA (f)->touch_y[i],
6215 i + base),
6216 arg);
6217
6218 inev.arg = arg;
6219 }
6220 }
6221 }
6222
6223 (*CloseTouchInputHandle) ((HANDLE) msg.msg.lParam);
6224 break;
6225
6059 default: 6226 default:
6060 /* Check for messages registered at runtime. */ 6227 /* Check for messages registered at runtime. */
6061 if (msg.msg.message == msh_mousewheel) 6228 if (msg.msg.message == msh_mousewheel)
@@ -7893,12 +8060,13 @@ w32_initialize (void)
7893#define LOAD_PROC(lib, fn) pfn##fn = (void *) GetProcAddress (lib, #fn) 8060#define LOAD_PROC(lib, fn) pfn##fn = (void *) GetProcAddress (lib, #fn)
7894 8061
7895 LOAD_PROC (user_lib, SetLayeredWindowAttributes); 8062 LOAD_PROC (user_lib, SetLayeredWindowAttributes);
8063 LOAD_PROC (user_lib, CloseTouchInputHandle);
8064 LOAD_PROC (user_lib, GetTouchInputInfo);
7896 8065
7897 /* PlgBlt is not available on Windows 9X. */ 8066 /* PlgBlt is not available on Windows 9X. */
7898 HMODULE hgdi = LoadLibrary ("gdi32.dll"); 8067 HMODULE hgdi = LoadLibrary ("gdi32.dll");
7899 if (hgdi) 8068 if (hgdi)
7900 LOAD_PROC (hgdi, PlgBlt); 8069 LOAD_PROC (hgdi, PlgBlt);
7901
7902#undef LOAD_PROC 8070#undef LOAD_PROC
7903 8071
7904 /* Ensure scrollbar handles are at least 5 pixels. */ 8072 /* Ensure scrollbar handles are at least 5 pixels. */
diff --git a/src/w32term.h b/src/w32term.h
index 38eac4230dd..1cdb165d2ed 100644
--- a/src/w32term.h
+++ b/src/w32term.h
@@ -434,6 +434,18 @@ struct w32_output
434 434
435 /* Whether or not this frame should be double buffered. */ 435 /* Whether or not this frame should be double buffered. */
436 unsigned want_paint_buffer : 1; 436 unsigned want_paint_buffer : 1;
437
438#define MAX_TOUCH_POINTS 10
439 /* Array of dwIDs of presently active touch points, or -1 when
440 unpopulated. */
441 int touch_ids[MAX_TOUCH_POINTS];
442
443 /* X and Y coordinates of active touchpoints. */
444 LONG touch_x[MAX_TOUCH_POINTS], touch_y[MAX_TOUCH_POINTS];
445
446 /* Base value for touch point identifiers registered by this
447 frame. */
448 EMACS_INT touch_base;
437}; 449};
438 450
439extern struct w32_output w32term_display; 451extern struct w32_output w32term_display;