Use the multitouch API. To disable system's defualt mouse emulation, set --native-touch=yes.
Unified · Split
| @@ -568,19 +568,29 @@ static void begin_dragging(struct vo_w32_state *w32) · 567 unmodified lines | ||
| 568 | 568 | mp_input_put_key(w32->input_ctx, MP_INPUT_RELEASE_ALL); |
| 569 | 569 | } |
| 570 | 570 | |
| 571 | −static bool handle_mouse_down(struct vo_w32_state *w32, int btn, int x, int y) | |
| 571 | +// If native touch is enabled and the mouse event is emulated, ignore it. | |
| 572 | +// See: <https://learn.microsoft.com/en-us/windows/win32/tablet/ | |
| 573 | +// system-events-and-mouse-messages#distinguishing-pen-input-from-mouse-and-touch> | |
| 574 | +static bool should_ignore_mouse_event(const struct vo_w32_state *w32) | |
| 572 | 575 | { |
| 576 | + return w32->opts->native_touch && ((GetMessageExtraInfo() & 0xFFFFFF00) == 0xFF515700); | |
| 577 | +} | |
| 578 | + | |
| 579 | +static void handle_mouse_down(struct vo_w32_state *w32, int btn, int x, int y) | |
| 580 | +{ | |
| 581 | + if (should_ignore_mouse_event(w32)) | |
| 582 | + return; | |
| 573 | 583 | btn |= mod_state(w32); |
| 574 | 584 | mp_input_put_key(w32->input_ctx, btn | MP_KEY_STATE_DOWN); |
| 575 | 585 | SetCapture(w32->window); |
| 576 | − return false; | |
| 577 | 586 | } |
| 578 | 587 | |
| 579 | 588 | static void handle_mouse_up(struct vo_w32_state *w32, int btn) |
| 580 | 589 | { |
| 590 | + if (should_ignore_mouse_event(w32)) | |
| 591 | + return; | |
| 581 | 592 | btn |= mod_state(w32); |
| 582 | 593 | mp_input_put_key(w32->input_ctx, btn | MP_KEY_STATE_UP); |
| 583 | − | |
| 584 | 594 | ReleaseCapture(); |
| 585 | 595 | } |
| 586 | 596 | |
| @@ -1315,6 +1325,19 @@ static void update_cursor_passthrough(const struct vo_w32_state *w32) · 728 unmodified lines | ||
| 1315 | 1325 | } |
| 1316 | 1326 | } |
| 1317 | 1327 | |
| 1328 | +static void update_native_touch(const struct vo_w32_state *w32) | |
| 1329 | +{ | |
| 1330 | + if (w32->parent) | |
| 1331 | + return; | |
| 1332 | + | |
| 1333 | + if (w32->opts->native_touch) { | |
| 1334 | + RegisterTouchWindow(w32->window, 0); | |
| 1335 | + } else { | |
| 1336 | + UnregisterTouchWindow(w32->window); | |
| 1337 | + mp_input_put_key(w32->input_ctx, MP_TOUCH_RELEASE_ALL); | |
| 1338 | + } | |
| 1339 | +} | |
| 1340 | + | |
| 1318 | 1341 | static void set_ime_conversion_mode(const struct vo_w32_state *w32, DWORD mode) |
| 1319 | 1342 | { |
| 1320 | 1343 | if (w32->parent) |
| @@ -1615,14 +1638,14 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, · 294 unmodified lines | ||
| 1615 | 1638 | if (x != w32->mouse_x || y != w32->mouse_y) { |
| 1616 | 1639 | w32->mouse_x = x; |
| 1617 | 1640 | w32->mouse_y = y; |
| 1618 | − mp_input_set_mouse_pos(w32->input_ctx, x, y); | |
| 1641 | + if (!should_ignore_mouse_event(w32)) | |
| 1642 | + mp_input_set_mouse_pos(w32->input_ctx, x, y); | |
| 1619 | 1643 | } |
| 1620 | 1644 | break; |
| 1621 | 1645 | } |
| 1622 | 1646 | case WM_LBUTTONDOWN: |
| 1623 | − if (handle_mouse_down(w32, MP_MBTN_LEFT, GET_X_LPARAM(lParam), | |
| 1624 | − GET_Y_LPARAM(lParam))) | |
| 1625 | − return 0; | |
| 1647 | + handle_mouse_down(w32, MP_MBTN_LEFT, GET_X_LPARAM(lParam), | |
| 1648 | + GET_Y_LPARAM(lParam)); | |
| 1626 | 1649 | break; |
| 1627 | 1650 | case WM_LBUTTONUP: |
| 1628 | 1651 | handle_mouse_up(w32, MP_MBTN_LEFT); |
| @@ -1713,6 +1736,26 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, · 84 unmodified lines | ||
| 1713 | 1736 | case WM_SHOWMENU: |
| 1714 | 1737 | mp_win32_menu_show(w32->menu_ctx, w32->window); |
| 1715 | 1738 | break; |
| 1739 | + case WM_TOUCH: { | |
| 1740 | + UINT count = LOWORD(wParam); | |
| 1741 | + TOUCHINPUT *inputs = talloc_array_ptrtype(NULL, inputs, count); | |
| 1742 | + if (GetTouchInputInfo((HTOUCHINPUT)lParam, count, inputs, sizeof(TOUCHINPUT))) { | |
| 1743 | + for (UINT i = 0; i < count; i++) { | |
| 1744 | + TOUCHINPUT *ti = &inputs[i]; | |
| 1745 | + POINT pt = {TOUCH_COORD_TO_PIXEL(ti->x), TOUCH_COORD_TO_PIXEL(ti->y)}; | |
| 1746 | + ScreenToClient(w32->window, &pt); | |
| 1747 | + if (ti->dwFlags & TOUCHEVENTF_DOWN) | |
| 1748 | + mp_input_add_touch_point(w32->input_ctx, ti->dwID, pt.x, pt.y); | |
| 1749 | + if (ti->dwFlags & TOUCHEVENTF_MOVE) | |
| 1750 | + mp_input_update_touch_point(w32->input_ctx, ti->dwID, pt.x, pt.y); | |
| 1751 | + if (ti->dwFlags & TOUCHEVENTF_UP) | |
| 1752 | + mp_input_remove_touch_point(w32->input_ctx, ti->dwID); | |
| 1753 | + } | |
| 1754 | + } | |
| 1755 | + CloseTouchInputHandle((HTOUCHINPUT)lParam); | |
| 1756 | + talloc_free(inputs); | |
| 1757 | + return 0; | |
| 1758 | + } | |
| 1716 | 1759 | } |
| 1717 | 1760 | |
| 1718 | 1761 | if (message == w32->tbtn_created_msg) { |
| @@ -1996,6 +2039,8 @@ static MP_THREAD_VOID gui_thread(void *ptr) · 277 unmodified lines | ||
| 1996 | 2039 | update_backdrop(w32); |
| 1997 | 2040 | if (w32->opts->cursor_passthrough) |
| 1998 | 2041 | update_cursor_passthrough(w32); |
| 2042 | + if (w32->opts->native_touch) | |
| 2043 | + update_native_touch(w32); | |
| 1999 | 2044 | |
| 2000 | 2045 | if (SUCCEEDED(OleInitialize(NULL))) { |
| 2001 | 2046 | ole_ok = true; |
| @@ -2199,6 +2244,8 @@ static int gui_thread_control(struct vo_w32_state *w32, int request, void *arg) · 197 unmodified lines | ||
| 2199 | 2244 | update_maximized_state(w32, false); |
| 2200 | 2245 | } else if (changed_option == &vo_opts->window_corners) { |
| 2201 | 2246 | update_corners_pref(w32); |
| 2247 | + } else if (changed_option == &vo_opts->native_touch) { | |
| 2248 | + update_native_touch(w32); | |
| 2202 | 2249 | } else if (changed_option == &vo_opts->geometry || changed_option == &vo_opts->autofit || |
| 2203 | 2250 | changed_option == &vo_opts->autofit_smaller || changed_option == &vo_opts->autofit_larger) |
| 2204 | 2251 | { |