Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(685)

Side by Side Diff: ui/views/win/hwnd_message_handler.cc

Issue 2904113002: Replacing WM_TOUCH with WM_POINTER for touch events on Wins 8+ (Closed)
Patch Set: Add a browser test Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/views/win/hwnd_message_handler.h" 5 #include "ui/views/win/hwnd_message_handler.h"
6 6
7 #include <dwmapi.h> 7 #include <dwmapi.h>
8 #include <oleacc.h> 8 #include <oleacc.h>
9 #include <shellapi.h> 9 #include <shellapi.h>
10 #include <tchar.h> 10 #include <tchar.h>
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
216 const int kAutoHideTaskbarThicknessPx = 2; 216 const int kAutoHideTaskbarThicknessPx = 2;
217 217
218 bool IsTopLevelWindow(HWND window) { 218 bool IsTopLevelWindow(HWND window) {
219 long style = ::GetWindowLong(window, GWL_STYLE); 219 long style = ::GetWindowLong(window, GWL_STYLE);
220 if (!(style & WS_CHILD)) 220 if (!(style & WS_CHILD))
221 return true; 221 return true;
222 HWND parent = ::GetParent(window); 222 HWND parent = ::GetParent(window);
223 return !parent || (parent == ::GetDesktopWindow()); 223 return !parent || (parent == ::GetDesktopWindow());
224 } 224 }
225 225
226 ui::EventType GetTouchEventType(POINTER_FLAGS pointer_flags) {
227 if (pointer_flags & POINTER_FLAG_DOWN)
228 return ui::ET_TOUCH_PRESSED;
229 if (pointer_flags & POINTER_FLAG_UPDATE)
230 return ui::ET_TOUCH_MOVED;
231 if (pointer_flags & POINTER_FLAG_UP)
232 return ui::ET_TOUCH_RELEASED;
233 return ui::ET_TOUCH_MOVED;
234 }
235
226 const int kTouchDownContextResetTimeout = 500; 236 const int kTouchDownContextResetTimeout = 500;
227 237
228 // Windows does not flag synthesized mouse messages from touch in all cases. 238 // Windows does not flag synthesized mouse messages from touch in all cases.
229 // This causes us grief as we don't want to process touch and mouse messages 239 // This causes us grief as we don't want to process touch and mouse messages
230 // concurrently. Hack as per msdn is to check if the time difference between 240 // concurrently. Hack as per msdn is to check if the time difference between
231 // the touch message and the mouse move is within 500 ms and at the same 241 // the touch message and the mouse move is within 500 ms and at the same
232 // location as the cursor. 242 // location as the cursor.
233 const int kSynthesizedMouseTouchMessagesTimeDifference = 500; 243 const int kSynthesizedMouseTouchMessagesTimeDifference = 500;
234 244
235 } // namespace 245 } // namespace
(...skipping 1429 matching lines...) Expand 10 before | Expand all | Expand 10 after
1665 } 1675 }
1666 1676
1667 UINT32 pointer_id = GET_POINTERID_WPARAM(w_param); 1677 UINT32 pointer_id = GET_POINTERID_WPARAM(w_param);
1668 using GetPointerTypeFn = BOOL(WINAPI*)(UINT32, POINTER_INPUT_TYPE*); 1678 using GetPointerTypeFn = BOOL(WINAPI*)(UINT32, POINTER_INPUT_TYPE*);
1669 POINTER_INPUT_TYPE pointer_type; 1679 POINTER_INPUT_TYPE pointer_type;
1670 static GetPointerTypeFn get_pointer_type = reinterpret_cast<GetPointerTypeFn>( 1680 static GetPointerTypeFn get_pointer_type = reinterpret_cast<GetPointerTypeFn>(
1671 GetProcAddress(GetModuleHandleA("user32.dll"), "GetPointerType")); 1681 GetProcAddress(GetModuleHandleA("user32.dll"), "GetPointerType"));
1672 // If the WM_POINTER messages are not sent from a stylus device, then we do 1682 // If the WM_POINTER messages are not sent from a stylus device, then we do
1673 // not handle them to make sure we do not change the current behavior of 1683 // not handle them to make sure we do not change the current behavior of
1674 // touch and mouse inputs. 1684 // touch and mouse inputs.
1675 if (!get_pointer_type || !get_pointer_type(pointer_id, &pointer_type) || 1685 if (!get_pointer_type || !get_pointer_type(pointer_id, &pointer_type)) {
1676 pointer_type != PT_PEN) {
1677 SetMsgHandled(FALSE); 1686 SetMsgHandled(FALSE);
1678 return -1; 1687 return -1;
1679 } 1688 }
1680 1689
1681 using GetPointerPenInfoFn = BOOL(WINAPI*)(UINT32, POINTER_PEN_INFO*); 1690 switch (pointer_type) {
1682 POINTER_PEN_INFO pointer_pen_info; 1691 case PT_TOUCH:
1683 static GetPointerPenInfoFn get_pointer_pen_info = 1692 return HandlePointerEventTypeTouch(message, w_param, l_param);
1684 reinterpret_cast<GetPointerPenInfoFn>( 1693 case PT_PEN:
1685 GetProcAddress(GetModuleHandleA("user32.dll"), "GetPointerPenInfo")); 1694 return HandlePointerEventTypePen(message, w_param, l_param);
1686 if (!get_pointer_pen_info || 1695 default:
1687 !get_pointer_pen_info(pointer_id, &pointer_pen_info)) { 1696 SetMsgHandled(FALSE);
1688 SetMsgHandled(FALSE); 1697 return -1;
1689 return -1;
1690 } 1698 }
1691
1692 // We are now creating a fake mouse event with pointer type of pen from
1693 // the WM_POINTER message and then setting up an associated pointer
1694 // details in the MouseEvent which contains the pen's information.
1695 ui::EventPointerType input_type = ui::EventPointerType::POINTER_TYPE_PEN;
1696 // TODO(lanwei): penFlags of PEN_FLAG_INVERTED may also indicate we are using
1697 // an eraser, but it is under debate. Please see
1698 // https://github.com/w3c/pointerevents/issues/134/.
1699 if (pointer_pen_info.penFlags & PEN_FLAG_ERASER)
1700 input_type = ui::EventPointerType::POINTER_TYPE_ERASER;
1701
1702 float pressure = static_cast<float>(pointer_pen_info.pressure) / 1024;
1703 float rotation = pointer_pen_info.rotation;
1704 int tilt_x = pointer_pen_info.tiltX;
1705 int tilt_y = pointer_pen_info.tiltY;
1706 POINT client_point = pointer_pen_info.pointerInfo.ptPixelLocationRaw;
1707 ScreenToClient(hwnd(), &client_point);
1708 gfx::Point point = gfx::Point(client_point.x, client_point.y);
1709 ui::EventType event_type = ui::ET_MOUSE_MOVED;
1710 int flag = 0;
1711 int click_count = 0;
1712 switch (message) {
1713 case WM_POINTERDOWN:
1714 event_type = ui::ET_MOUSE_PRESSED;
1715 if (pointer_pen_info.pointerInfo.ButtonChangeType ==
1716 POINTER_CHANGE_SECONDBUTTON_DOWN) {
1717 flag = ui::EF_RIGHT_MOUSE_BUTTON;
1718 } else {
1719 flag = ui::EF_LEFT_MOUSE_BUTTON;
1720 }
1721 click_count = 1;
1722 break;
1723 case WM_POINTERUP:
1724 event_type = ui::ET_MOUSE_RELEASED;
1725 if (pointer_pen_info.pointerInfo.ButtonChangeType ==
1726 POINTER_CHANGE_SECONDBUTTON_UP) {
1727 flag = ui::EF_RIGHT_MOUSE_BUTTON;
1728 } else {
1729 flag = ui::EF_LEFT_MOUSE_BUTTON;
1730 }
1731 click_count = 1;
1732 break;
1733 case WM_POINTERUPDATE:
1734 event_type = ui::ET_MOUSE_DRAGGED;
1735 if (pointer_pen_info.pointerInfo.pointerFlags &
1736 POINTER_FLAG_FIRSTBUTTON) {
1737 flag = ui::EF_LEFT_MOUSE_BUTTON;
1738 } else if (pointer_pen_info.pointerInfo.pointerFlags &
1739 POINTER_FLAG_SECONDBUTTON) {
1740 flag = ui::EF_RIGHT_MOUSE_BUTTON;
1741 } else {
1742 event_type = ui::ET_MOUSE_MOVED;
1743 }
1744 break;
1745 case WM_POINTERENTER:
1746 event_type = ui::ET_MOUSE_ENTERED;
1747 break;
1748 case WM_POINTERLEAVE:
1749 event_type = ui::ET_MOUSE_EXITED;
1750 break;
1751 default:
1752 NOTREACHED();
1753 }
1754 ui::PointerDetails pointer_details(
1755 input_type, pointer_id, /* radius_x */ 0.0f, /* radius_y */ 0.0f,
1756 pressure, tilt_x, tilt_y, /* tangential_pressure */ 0.0f, rotation);
1757 ui::MouseEvent event(event_type, point, point, base::TimeTicks::Now(), flag,
1758 flag, pointer_details);
1759 event.SetClickCount(click_count);
1760
1761 // There are cases where the code handling the message destroys the
1762 // window, so use the weak ptr to check if destruction occured or not.
1763 base::WeakPtr<HWNDMessageHandler> ref(weak_factory_.GetWeakPtr());
1764 bool handled = delegate_->HandleMouseEvent(event);
1765
1766 if (ref)
1767 SetMsgHandled(handled);
1768 return 0;
1769 } 1699 }
1770 1700
1771 void HWNDMessageHandler::OnMove(const gfx::Point& point) { 1701 void HWNDMessageHandler::OnMove(const gfx::Point& point) {
1772 delegate_->HandleMove(); 1702 delegate_->HandleMove();
1773 SetMsgHandled(FALSE); 1703 SetMsgHandled(FALSE);
1774 } 1704 }
1775 1705
1776 void HWNDMessageHandler::OnMoving(UINT param, const RECT* new_bounds) { 1706 void HWNDMessageHandler::OnMoving(UINT param, const RECT* new_bounds) {
1777 delegate_->HandleMove(); 1707 delegate_->HandleMove();
1778 } 1708 }
(...skipping 920 matching lines...) Expand 10 before | Expand all | Expand 10 after
2699 // Please refer to the HandleMouseInputForCaption() function for more 2629 // Please refer to the HandleMouseInputForCaption() function for more
2700 // information. 2630 // information.
2701 if (!handled) 2631 if (!handled)
2702 handled = HandleMouseInputForCaption(message, w_param, l_param); 2632 handled = HandleMouseInputForCaption(message, w_param, l_param);
2703 2633
2704 if (ref.get()) 2634 if (ref.get())
2705 SetMsgHandled(handled); 2635 SetMsgHandled(handled);
2706 return 0; 2636 return 0;
2707 } 2637 }
2708 2638
2639 LRESULT HWNDMessageHandler::HandlePointerEventTypeTouch(UINT message,
2640 WPARAM w_param,
2641 LPARAM l_param) {
2642 UINT32 pointer_id = GET_POINTERID_WPARAM(w_param);
sky 2017/06/07 19:42:45 GET_POINTERID_WPARAM is only available on >= win 8
lanwei 2017/06/22 18:38:45 In HWNDMessageHandler::OnPointerEvent, I checked t
2643 using GetPointerTouchInfoFn = BOOL(WINAPI*)(UINT32, POINTER_TOUCH_INFO*);
2644 POINTER_TOUCH_INFO pointer_touch_info;
2645 static GetPointerTouchInfoFn get_pointer_touch_info =
2646 reinterpret_cast<GetPointerTouchInfoFn>(GetProcAddress(
2647 GetModuleHandleA("user32.dll"), "GetPointerTouchInfo"));
2648 if (!get_pointer_touch_info ||
2649 !get_pointer_touch_info(pointer_id, &pointer_touch_info)) {
2650 SetMsgHandled(FALSE);
2651 return -1;
2652 }
2653
2654 POINTER_INFO pointer_info = pointer_touch_info.pointerInfo;
2655
2656 POINT client_point = pointer_info.ptPixelLocationRaw;
2657 ScreenToClient(hwnd(), &client_point);
2658 gfx::Point touch_point = gfx::Point(client_point.x, client_point.y);
sky 2017/06/07 19:42:45 Does this need to be converted for dips?
lanwei 2017/06/22 18:38:45 No.
2659
2660 POINTER_FLAGS pointer_flags = pointer_info.pointerFlags;
2661 ui::EventType event_type = GetTouchEventType(pointer_flags);
2662 const base::TimeTicks event_time = base::TimeTicks::Now();
sky 2017/06/07 19:42:45 Can't you use the time from the event?
lanwei 2017/06/22 18:38:45 What event? We do not have time information from w
sky 2017/06/22 20:54:21 Sorry, I believe you want EventTimeForNow().
lanwei 2017/06/23 20:06:05 Done.
2663
2664 float pressure = static_cast<float>(pointer_touch_info.pressure) / 1024;
sky 2017/06/07 19:42:45 Where does the 1024 come from?
lanwei 2017/06/22 18:38:45 A pressure is normalized to a range between 0 and
2665 float radius_x =
2666 (pointer_touch_info.rcContact.right - pointer_touch_info.rcContact.left) /
2667 2.0;
2668 float radius_y =
2669 (pointer_touch_info.rcContact.bottom - pointer_touch_info.rcContact.top) /
2670 2.0;
2671 int rotation_angle = pointer_touch_info.orientation;
2672 rotation_angle %= 180;
2673 if (rotation_angle < 0)
2674 rotation_angle += 180;
2675
2676 ui::TouchEvent event(
2677 event_type, touch_point, event_time,
2678 ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, pointer_id,
2679 radius_x, radius_y, pressure, 0.0f, 0.0f, 0.0f,
2680 pointer_touch_info.orientation),
2681 ui::GetModifiersFromKeyState(), rotation_angle);
2682
2683 event.latency()->AddLatencyNumberWithTimestamp(
2684 ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, 0, event_time, 1);
2685
2686 // There are cases where the code handling the message destroys the
2687 // window, so use the weak ptr to check if destruction occured or not.
2688 base::WeakPtr<HWNDMessageHandler> ref(weak_factory_.GetWeakPtr());
2689 delegate_->HandleTouchEvent(event);
2690
2691 if (ref)
2692 SetMsgHandled(TRUE);
2693 return 0;
2694 }
2695
2696 LRESULT HWNDMessageHandler::HandlePointerEventTypePen(UINT message,
2697 WPARAM w_param,
2698 LPARAM l_param) {
2699 UINT32 pointer_id = GET_POINTERID_WPARAM(w_param);
2700 using GetPointerPenInfoFn = BOOL(WINAPI*)(UINT32, POINTER_PEN_INFO*);
2701 POINTER_PEN_INFO pointer_pen_info;
2702 static GetPointerPenInfoFn get_pointer_pen_info =
2703 reinterpret_cast<GetPointerPenInfoFn>(
2704 GetProcAddress(GetModuleHandleA("user32.dll"), "GetPointerPenInfo"));
2705 if (!get_pointer_pen_info ||
2706 !get_pointer_pen_info(pointer_id, &pointer_pen_info)) {
2707 SetMsgHandled(FALSE);
2708 return -1;
2709 }
2710
2711 // We are now creating a fake mouse event with pointer type of pen from
2712 // the WM_POINTER message and then setting up an associated pointer
2713 // details in the MouseEvent which contains the pen's information.
2714 ui::EventPointerType input_type = ui::EventPointerType::POINTER_TYPE_PEN;
2715 // TODO(lanwei): penFlags of PEN_FLAG_INVERTED may also indicate we are using
2716 // an eraser, but it is under debate. Please see
2717 // https://github.com/w3c/pointerevents/issues/134/.
2718 if (pointer_pen_info.penFlags & PEN_FLAG_ERASER)
2719 input_type = ui::EventPointerType::POINTER_TYPE_ERASER;
2720
2721 float pressure = static_cast<float>(pointer_pen_info.pressure) / 1024;
sky 2017/06/07 19:42:45 Same question about 1024.
lanwei 2017/06/22 18:38:45 Done.
2722 float rotation = pointer_pen_info.rotation;
2723 int tilt_x = pointer_pen_info.tiltX;
2724 int tilt_y = pointer_pen_info.tiltY;
2725 POINT client_point = pointer_pen_info.pointerInfo.ptPixelLocationRaw;
2726 ScreenToClient(hwnd(), &client_point);
2727 gfx::Point point = gfx::Point(client_point.x, client_point.y);
sky 2017/06/07 19:42:45 And coordinate conversion.
lanwei 2017/06/22 18:38:45 We do not need coordinate conversion.
2728 ui::EventType event_type = ui::ET_MOUSE_MOVED;
2729 int flag = 0;
2730 int click_count = 0;
2731 switch (message) {
2732 case WM_POINTERDOWN:
2733 event_type = ui::ET_MOUSE_PRESSED;
2734 if (pointer_pen_info.pointerInfo.ButtonChangeType ==
2735 POINTER_CHANGE_SECONDBUTTON_DOWN) {
2736 flag = ui::EF_RIGHT_MOUSE_BUTTON;
2737 } else {
2738 flag = ui::EF_LEFT_MOUSE_BUTTON;
2739 }
2740 click_count = 1;
2741 break;
2742 case WM_POINTERUP:
2743 event_type = ui::ET_MOUSE_RELEASED;
2744 if (pointer_pen_info.pointerInfo.ButtonChangeType ==
2745 POINTER_CHANGE_SECONDBUTTON_UP) {
2746 flag = ui::EF_RIGHT_MOUSE_BUTTON;
2747 } else {
2748 flag = ui::EF_LEFT_MOUSE_BUTTON;
2749 }
2750 click_count = 1;
2751 break;
2752 case WM_POINTERUPDATE:
2753 event_type = ui::ET_MOUSE_DRAGGED;
2754 if (pointer_pen_info.pointerInfo.pointerFlags &
2755 POINTER_FLAG_FIRSTBUTTON) {
2756 flag = ui::EF_LEFT_MOUSE_BUTTON;
2757 } else if (pointer_pen_info.pointerInfo.pointerFlags &
2758 POINTER_FLAG_SECONDBUTTON) {
2759 flag = ui::EF_RIGHT_MOUSE_BUTTON;
2760 } else {
2761 event_type = ui::ET_MOUSE_MOVED;
2762 }
2763 break;
2764 case WM_POINTERENTER:
2765 event_type = ui::ET_MOUSE_ENTERED;
2766 break;
2767 case WM_POINTERLEAVE:
2768 event_type = ui::ET_MOUSE_EXITED;
2769 break;
2770 default:
2771 NOTREACHED();
2772 }
2773 ui::PointerDetails pointer_details(
2774 input_type, pointer_id, /* radius_x */ 0.0f, /* radius_y */ 0.0f,
2775 pressure, tilt_x, tilt_y, /* tangential_pressure */ 0.0f, rotation);
2776 ui::MouseEvent event(event_type, point, point, base::TimeTicks::Now(), flag,
2777 flag, pointer_details);
2778 event.SetClickCount(click_count);
2779
2780 // There are cases where the code handling the message destroys the
2781 // window, so use the weak ptr to check if destruction occured or not.
2782 base::WeakPtr<HWNDMessageHandler> ref(weak_factory_.GetWeakPtr());
2783 bool handled = delegate_->HandleMouseEvent(event);
2784
2785 if (ref)
2786 SetMsgHandled(handled);
2787 return 0;
2788 }
2789
2709 bool HWNDMessageHandler::IsSynthesizedMouseMessage(unsigned int message, 2790 bool HWNDMessageHandler::IsSynthesizedMouseMessage(unsigned int message,
2710 int message_time, 2791 int message_time,
2711 LPARAM l_param) { 2792 LPARAM l_param) {
2712 if (ui::IsMouseEventFromTouch(message)) 2793 if (ui::IsMouseEventFromTouch(message))
2713 return true; 2794 return true;
2714 // Ignore mouse messages which occur at the same location as the current 2795 // Ignore mouse messages which occur at the same location as the current
2715 // cursor position and within a time difference of 500 ms from the last 2796 // cursor position and within a time difference of 500 ms from the last
2716 // touch message. 2797 // touch message.
2717 if (last_touch_message_time_ && message_time >= last_touch_message_time_ && 2798 if (last_touch_message_time_ && message_time >= last_touch_message_time_ &&
2718 ((message_time - last_touch_message_time_) <= 2799 ((message_time - last_touch_message_time_) <=
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
2909 MONITORINFO monitor_info = {sizeof(monitor_info)}; 2990 MONITORINFO monitor_info = {sizeof(monitor_info)};
2910 GetMonitorInfo(MonitorFromWindow(hwnd(), MONITOR_DEFAULTTOPRIMARY), 2991 GetMonitorInfo(MonitorFromWindow(hwnd(), MONITOR_DEFAULTTOPRIMARY),
2911 &monitor_info); 2992 &monitor_info);
2912 gfx::Rect shrunk_rect(monitor_info.rcMonitor); 2993 gfx::Rect shrunk_rect(monitor_info.rcMonitor);
2913 shrunk_rect.set_height(shrunk_rect.height() - 1); 2994 shrunk_rect.set_height(shrunk_rect.height() - 1);
2914 background_fullscreen_hack_ = true; 2995 background_fullscreen_hack_ = true;
2915 SetBoundsInternal(shrunk_rect, false); 2996 SetBoundsInternal(shrunk_rect, false);
2916 } 2997 }
2917 2998
2918 } // namespace views 2999 } // namespace views
OLDNEW
« ui/base/test/ui_controls_internal_win.cc ('K') | « ui/views/win/hwnd_message_handler.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698