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

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: wm touch Created 3 years, 5 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 924 matching lines...) Expand 10 before | Expand all | Expand 10 after
2703 // Please refer to the HandleMouseInputForCaption() function for more 2633 // Please refer to the HandleMouseInputForCaption() function for more
2704 // information. 2634 // information.
2705 if (!handled) 2635 if (!handled)
2706 handled = HandleMouseInputForCaption(message, w_param, l_param); 2636 handled = HandleMouseInputForCaption(message, w_param, l_param);
2707 2637
2708 if (ref.get()) 2638 if (ref.get())
2709 SetMsgHandled(handled); 2639 SetMsgHandled(handled);
2710 return 0; 2640 return 0;
2711 } 2641 }
2712 2642
2643 LRESULT HWNDMessageHandler::HandlePointerEventTypeTouch(UINT message,
2644 WPARAM w_param,
2645 LPARAM l_param) {
2646 UINT32 pointer_id = GET_POINTERID_WPARAM(w_param);
2647 using GetPointerTouchInfoFn = BOOL(WINAPI*)(UINT32, POINTER_TOUCH_INFO*);
2648 POINTER_TOUCH_INFO pointer_touch_info;
2649 static GetPointerTouchInfoFn get_pointer_touch_info =
2650 reinterpret_cast<GetPointerTouchInfoFn>(GetProcAddress(
2651 GetModuleHandleA("user32.dll"), "GetPointerTouchInfo"));
2652 if (!get_pointer_touch_info ||
2653 !get_pointer_touch_info(pointer_id, &pointer_touch_info)) {
2654 SetMsgHandled(FALSE);
2655 return -1;
2656 }
2657
2658 POINTER_INFO pointer_info = pointer_touch_info.pointerInfo;
2659
2660 POINT client_point = pointer_info.ptPixelLocationRaw;
2661 ScreenToClient(hwnd(), &client_point);
2662 gfx::Point touch_point = gfx::Point(client_point.x, client_point.y);
sky 2017/06/27 02:19:48 These coordinates are pixels, but views expects DI
lanwei 2017/06/27 18:55:42 I did not see any conversion to DIPs in HWNDMessag
sky 2017/06/27 22:36:42 I think it's actually done in WindowEventDispatche
2663
2664 POINTER_FLAGS pointer_flags = pointer_info.pointerFlags;
2665 ui::EventType event_type = GetTouchEventType(pointer_flags);
2666 const base::TimeTicks event_time = ui::EventTimeForNow();
2667
2668 // The pressure from POINTER_TOUCH_INFO is normalized to a range between 0
2669 // and 1024, but we define the pressure of the range of [0,1].
2670 float pressure = static_cast<float>(pointer_touch_info.pressure) / 1024;
2671 float radius_x =
2672 (pointer_touch_info.rcContact.right - pointer_touch_info.rcContact.left) /
2673 2.0;
2674 float radius_y =
2675 (pointer_touch_info.rcContact.bottom - pointer_touch_info.rcContact.top) /
2676 2.0;
2677 int rotation_angle = pointer_touch_info.orientation;
2678 rotation_angle %= 180;
2679 if (rotation_angle < 0)
2680 rotation_angle += 180;
2681
2682 ui::TouchEvent event(
2683 event_type, touch_point, event_time,
2684 ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, pointer_id,
2685 radius_x, radius_y, pressure, 0.0f, 0.0f, 0.0f,
2686 pointer_touch_info.orientation),
2687 ui::GetModifiersFromKeyState(), rotation_angle);
2688
2689 event.latency()->AddLatencyNumberWithTimestamp(
2690 ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, 0, event_time, 1);
2691
2692 // There are cases where the code handling the message destroys the
2693 // window, so use the weak ptr to check if destruction occured or not.
2694 base::WeakPtr<HWNDMessageHandler> ref(weak_factory_.GetWeakPtr());
2695 delegate_->HandleTouchEvent(event);
2696
2697 if (ref)
2698 SetMsgHandled(TRUE);
2699 return 0;
2700 }
2701
2702 LRESULT HWNDMessageHandler::HandlePointerEventTypePen(UINT message,
2703 WPARAM w_param,
2704 LPARAM l_param) {
2705 UINT32 pointer_id = GET_POINTERID_WPARAM(w_param);
2706 using GetPointerPenInfoFn = BOOL(WINAPI*)(UINT32, POINTER_PEN_INFO*);
2707 POINTER_PEN_INFO pointer_pen_info;
2708 static GetPointerPenInfoFn get_pointer_pen_info =
2709 reinterpret_cast<GetPointerPenInfoFn>(
2710 GetProcAddress(GetModuleHandleA("user32.dll"), "GetPointerPenInfo"));
2711 if (!get_pointer_pen_info ||
2712 !get_pointer_pen_info(pointer_id, &pointer_pen_info)) {
2713 SetMsgHandled(FALSE);
2714 return -1;
2715 }
2716
2717 // We are now creating a fake mouse event with pointer type of pen from
2718 // the WM_POINTER message and then setting up an associated pointer
2719 // details in the MouseEvent which contains the pen's information.
2720 ui::EventPointerType input_type = ui::EventPointerType::POINTER_TYPE_PEN;
2721 // TODO(lanwei): penFlags of PEN_FLAG_INVERTED may also indicate we are using
2722 // an eraser, but it is under debate. Please see
2723 // https://github.com/w3c/pointerevents/issues/134/.
2724 if (pointer_pen_info.penFlags & PEN_FLAG_ERASER)
2725 input_type = ui::EventPointerType::POINTER_TYPE_ERASER;
2726
2727 float pressure = static_cast<float>(pointer_pen_info.pressure) / 1024;
2728 float rotation = pointer_pen_info.rotation;
2729 int tilt_x = pointer_pen_info.tiltX;
2730 int tilt_y = pointer_pen_info.tiltY;
2731 POINT client_point = pointer_pen_info.pointerInfo.ptPixelLocationRaw;
2732 ScreenToClient(hwnd(), &client_point);
2733 gfx::Point point = gfx::Point(client_point.x, client_point.y);
2734 ui::EventType event_type = ui::ET_MOUSE_MOVED;
2735 int flag = 0;
2736 int click_count = 0;
2737 switch (message) {
2738 case WM_POINTERDOWN:
2739 event_type = ui::ET_MOUSE_PRESSED;
2740 if (pointer_pen_info.pointerInfo.ButtonChangeType ==
2741 POINTER_CHANGE_SECONDBUTTON_DOWN) {
2742 flag = ui::EF_RIGHT_MOUSE_BUTTON;
2743 } else {
2744 flag = ui::EF_LEFT_MOUSE_BUTTON;
2745 }
2746 click_count = 1;
2747 break;
2748 case WM_POINTERUP:
2749 event_type = ui::ET_MOUSE_RELEASED;
2750 if (pointer_pen_info.pointerInfo.ButtonChangeType ==
2751 POINTER_CHANGE_SECONDBUTTON_UP) {
2752 flag = ui::EF_RIGHT_MOUSE_BUTTON;
2753 } else {
2754 flag = ui::EF_LEFT_MOUSE_BUTTON;
2755 }
2756 click_count = 1;
2757 break;
2758 case WM_POINTERUPDATE:
2759 event_type = ui::ET_MOUSE_DRAGGED;
2760 if (pointer_pen_info.pointerInfo.pointerFlags &
2761 POINTER_FLAG_FIRSTBUTTON) {
2762 flag = ui::EF_LEFT_MOUSE_BUTTON;
2763 } else if (pointer_pen_info.pointerInfo.pointerFlags &
2764 POINTER_FLAG_SECONDBUTTON) {
2765 flag = ui::EF_RIGHT_MOUSE_BUTTON;
2766 } else {
2767 event_type = ui::ET_MOUSE_MOVED;
2768 }
2769 break;
2770 case WM_POINTERENTER:
2771 event_type = ui::ET_MOUSE_ENTERED;
2772 break;
2773 case WM_POINTERLEAVE:
2774 event_type = ui::ET_MOUSE_EXITED;
2775 break;
2776 default:
2777 NOTREACHED();
2778 }
2779 ui::PointerDetails pointer_details(
2780 input_type, pointer_id, /* radius_x */ 0.0f, /* radius_y */ 0.0f,
2781 pressure, tilt_x, tilt_y, /* tangential_pressure */ 0.0f, rotation);
2782 ui::MouseEvent event(event_type, point, point, base::TimeTicks::Now(), flag,
2783 flag, pointer_details);
2784 event.SetClickCount(click_count);
2785
2786 // There are cases where the code handling the message destroys the
2787 // window, so use the weak ptr to check if destruction occured or not.
2788 base::WeakPtr<HWNDMessageHandler> ref(weak_factory_.GetWeakPtr());
2789 bool handled = delegate_->HandleMouseEvent(event);
2790
2791 if (ref)
2792 SetMsgHandled(handled);
2793 return 0;
2794 }
2795
2713 bool HWNDMessageHandler::IsSynthesizedMouseMessage(unsigned int message, 2796 bool HWNDMessageHandler::IsSynthesizedMouseMessage(unsigned int message,
2714 int message_time, 2797 int message_time,
2715 LPARAM l_param) { 2798 LPARAM l_param) {
2716 if (ui::IsMouseEventFromTouch(message)) 2799 if (ui::IsMouseEventFromTouch(message))
2717 return true; 2800 return true;
2718 // Ignore mouse messages which occur at the same location as the current 2801 // Ignore mouse messages which occur at the same location as the current
2719 // cursor position and within a time difference of 500 ms from the last 2802 // cursor position and within a time difference of 500 ms from the last
2720 // touch message. 2803 // touch message.
2721 if (last_touch_message_time_ && message_time >= last_touch_message_time_ && 2804 if (last_touch_message_time_ && message_time >= last_touch_message_time_ &&
2722 ((message_time - last_touch_message_time_) <= 2805 ((message_time - last_touch_message_time_) <=
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
2913 MONITORINFO monitor_info = {sizeof(monitor_info)}; 2996 MONITORINFO monitor_info = {sizeof(monitor_info)};
2914 GetMonitorInfo(MonitorFromWindow(hwnd(), MONITOR_DEFAULTTOPRIMARY), 2997 GetMonitorInfo(MonitorFromWindow(hwnd(), MONITOR_DEFAULTTOPRIMARY),
2915 &monitor_info); 2998 &monitor_info);
2916 gfx::Rect shrunk_rect(monitor_info.rcMonitor); 2999 gfx::Rect shrunk_rect(monitor_info.rcMonitor);
2917 shrunk_rect.set_height(shrunk_rect.height() - 1); 3000 shrunk_rect.set_height(shrunk_rect.height() - 1);
2918 background_fullscreen_hack_ = true; 3001 background_fullscreen_hack_ = true;
2919 SetBoundsInternal(shrunk_rect, false); 3002 SetBoundsInternal(shrunk_rect, false);
2920 } 3003 }
2921 3004
2922 } // namespace views 3005 } // namespace views
OLDNEW
« ui/base/test/ui_controls.h ('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