| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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); |
| 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 Loading... |
| 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 |
| OLD | NEW |