diff options
| author | Po Lu | 2024-06-09 17:44:25 +0800 |
|---|---|---|
| committer | Po Lu | 2024-06-09 20:40:58 +0800 |
| commit | 5eb729c0b36a31869cf4928bc7bf5111b6f59ebb (patch) | |
| tree | 322e1c28ceb9e146c610ca6fc01473d374b9242c /src | |
| parent | dcd95d7a77dc1016de72860ecb0623b6377bdc65 (diff) | |
| download | emacs-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.c | 36 | ||||
| -rw-r--r-- | src/w32term.c | 170 | ||||
| -rw-r--r-- | src/w32term.h | 12 |
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); |
| 217 | typedef BOOL (WINAPI * WTSUnRegisterSessionNotification_Proc) (HWND hwnd); | 217 | typedef BOOL (WINAPI * WTSUnRegisterSessionNotification_Proc) (HWND hwnd); |
| 218 | 218 | ||
| 219 | typedef BOOL (WINAPI * RegisterTouchWindow_proc) (HWND, ULONG); | ||
| 220 | |||
| 219 | TrackMouseEvent_Proc track_mouse_event_fn = NULL; | 221 | TrackMouseEvent_Proc track_mouse_event_fn = NULL; |
| 220 | ImmGetCompositionString_Proc get_composition_string_fn = NULL; | 222 | ImmGetCompositionString_Proc get_composition_string_fn = NULL; |
| 221 | ImmGetContext_Proc get_ime_context_fn = NULL; | 223 | ImmGetContext_Proc get_ime_context_fn = NULL; |
| @@ -234,6 +236,7 @@ SetWindowTheme_Proc SetWindowTheme_fn = NULL; | |||
| 234 | DwmSetWindowAttribute_Proc DwmSetWindowAttribute_fn = NULL; | 236 | DwmSetWindowAttribute_Proc DwmSetWindowAttribute_fn = NULL; |
| 235 | WTSUnRegisterSessionNotification_Proc WTSUnRegisterSessionNotification_fn = NULL; | 237 | WTSUnRegisterSessionNotification_Proc WTSUnRegisterSessionNotification_fn = NULL; |
| 236 | WTSRegisterSessionNotification_Proc WTSRegisterSessionNotification_fn = NULL; | 238 | WTSRegisterSessionNotification_Proc WTSRegisterSessionNotification_fn = NULL; |
| 239 | RegisterTouchWindow_proc RegisterTouchWindow_fn = NULL; | ||
| 237 | 240 | ||
| 238 | extern AppendMenuW_Proc unicode_append_menu; | 241 | extern 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. */ |
| 121 | BOOL (WINAPI *pfnPlgBlt) (HDC, const POINT *, HDC, int, int, int, int, HBITMAP, int, int); | 121 | BOOL (WINAPI *pfnPlgBlt) (HDC, const POINT *, HDC, int, int, int, int, HBITMAP, int, int); |
| 122 | 122 | ||
| 123 | /* Functions that extract data from touch-screen events. */ | ||
| 124 | typedef BOOL (WINAPI * CloseTouchInputHandle_proc) (HANDLE); | ||
| 125 | typedef BOOL (WINAPI * GetTouchInputInfo_proc) (HANDLE, UINT, PTOUCHINPUT, int); | ||
| 126 | |||
| 127 | CloseTouchInputHandle_proc pfnCloseTouchInputHandle; | ||
| 128 | GetTouchInputInfo_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 | |||
| 163 | typedef 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. */ |
| 143 | HWND w32_system_caret_hwnd; | 179 | HWND w32_system_caret_hwnd; |
| 144 | int w32_system_caret_height; | 180 | int 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 | ||
| 439 | extern struct w32_output w32term_display; | 451 | extern struct w32_output w32term_display; |