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;
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;
/* 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)
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;
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;
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");
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;
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;
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
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;
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);
}
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;
+ }
}
}
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);
}
}
}