| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 "views/widget/widget_win.h" | 5 #include "views/widget/widget_win.h" |
| 6 | 6 |
| 7 #include "app/gfx/canvas.h" | 7 #include "app/gfx/canvas.h" |
| 8 #include "app/gfx/path.h" | 8 #include "app/gfx/path.h" |
| 9 #include "app/win_util.h" | 9 #include "app/win_util.h" |
| 10 #include "base/gfx/native_theme.h" | 10 #include "base/gfx/native_theme.h" |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 137 : close_widget_factory_(this), | 137 : close_widget_factory_(this), |
| 138 active_mouse_tracking_flags_(0), | 138 active_mouse_tracking_flags_(0), |
| 139 has_capture_(false), | 139 has_capture_(false), |
| 140 window_style_(0), | 140 window_style_(0), |
| 141 window_ex_style_(kWindowDefaultExStyle), | 141 window_ex_style_(kWindowDefaultExStyle), |
| 142 use_layered_buffer_(true), | 142 use_layered_buffer_(true), |
| 143 layered_alpha_(255), | 143 layered_alpha_(255), |
| 144 delete_on_destroy_(true), | 144 delete_on_destroy_(true), |
| 145 can_update_layered_window_(true), | 145 can_update_layered_window_(true), |
| 146 last_mouse_event_was_move_(false), | 146 last_mouse_event_was_move_(false), |
| 147 mouse_buttons_are_swapped_(0 != GetSystemMetrics(SM_SWAPBUTTON)), |
| 148 buttons_pressed_(0), |
| 149 released_buttons_out_of_order_(0), |
| 147 is_mouse_down_(false), | 150 is_mouse_down_(false), |
| 148 is_window_(false), | 151 is_window_(false), |
| 149 class_style_(CS_DBLCLKS), | 152 class_style_(CS_DBLCLKS), |
| 150 hwnd_(NULL) { | 153 hwnd_(NULL) { |
| 154 left_button_code_ = mouse_buttons_are_swapped_ ? VK_RBUTTON : VK_LBUTTON; |
| 155 right_button_code_ = mouse_buttons_are_swapped_ ? VK_LBUTTON : VK_RBUTTON; |
| 151 } | 156 } |
| 152 | 157 |
| 153 WidgetWin::~WidgetWin() { | 158 WidgetWin::~WidgetWin() { |
| 154 MessageLoopForUI::current()->RemoveObserver(this); | 159 MessageLoopForUI::current()->RemoveObserver(this); |
| 155 } | 160 } |
| 156 | 161 |
| 157 void WidgetWin::Init(HWND parent, const gfx::Rect& bounds) { | 162 void WidgetWin::Init(HWND parent, const gfx::Rect& bounds) { |
| 158 if (window_style_ == 0) | 163 if (window_style_ == 0) |
| 159 window_style_ = parent ? kWindowDefaultChildStyle : kWindowDefaultStyle; | 164 window_style_ = parent ? kWindowDefaultChildStyle : kWindowDefaultStyle; |
| 160 | 165 |
| (...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 609 KeyEvent event(Event::ET_KEY_PRESSED, c, rep_cnt, flags); | 614 KeyEvent event(Event::ET_KEY_PRESSED, c, rep_cnt, flags); |
| 610 SetMsgHandled(root_view_->ProcessKeyEvent(event)); | 615 SetMsgHandled(root_view_->ProcessKeyEvent(event)); |
| 611 } | 616 } |
| 612 | 617 |
| 613 void WidgetWin::OnKeyUp(TCHAR c, UINT rep_cnt, UINT flags) { | 618 void WidgetWin::OnKeyUp(TCHAR c, UINT rep_cnt, UINT flags) { |
| 614 KeyEvent event(Event::ET_KEY_RELEASED, c, rep_cnt, flags); | 619 KeyEvent event(Event::ET_KEY_RELEASED, c, rep_cnt, flags); |
| 615 SetMsgHandled(root_view_->ProcessKeyEvent(event)); | 620 SetMsgHandled(root_view_->ProcessKeyEvent(event)); |
| 616 } | 621 } |
| 617 | 622 |
| 618 void WidgetWin::OnLButtonDown(UINT flags, const CPoint& point) { | 623 void WidgetWin::OnLButtonDown(UINT flags, const CPoint& point) { |
| 619 ProcessMousePressed(point, flags | MK_LBUTTON, false, false); | 624 // Clear out-of-order release flag in case the "button released" event |
| 625 // was truly completely swallowed. |
| 626 released_buttons_out_of_order_ &= ~left_button_code_; |
| 627 if (ProcessMousePressed(point, flags | MK_LBUTTON, false, false)) |
| 628 buttons_pressed_ |= left_button_code_; |
| 620 } | 629 } |
| 621 | 630 |
| 622 void WidgetWin::OnLButtonUp(UINT flags, const CPoint& point) { | 631 void WidgetWin::OnLButtonUp(UINT flags, const CPoint& point) { |
| 623 ProcessMouseReleased(point, flags | MK_LBUTTON); | 632 // If we already generated the event for this button out of order, |
| 633 // avoid doing it twice. |
| 634 if (0 == (released_buttons_out_of_order_ & left_button_code_)) { |
| 635 ProcessMouseReleased(point, flags | MK_LBUTTON); |
| 636 } |
| 637 released_buttons_out_of_order_ &= ~left_button_code_; |
| 638 buttons_pressed_ &= ~left_button_code_; |
| 624 } | 639 } |
| 625 | 640 |
| 626 void WidgetWin::OnLButtonDblClk(UINT flags, const CPoint& point) { | 641 void WidgetWin::OnLButtonDblClk(UINT flags, const CPoint& point) { |
| 627 ProcessMousePressed(point, flags | MK_LBUTTON, true, false); | 642 ProcessMousePressed(point, flags | MK_LBUTTON, true, false); |
| 628 } | 643 } |
| 629 | 644 |
| 630 void WidgetWin::OnMButtonDown(UINT flags, const CPoint& point) { | 645 void WidgetWin::OnMButtonDown(UINT flags, const CPoint& point) { |
| 631 ProcessMousePressed(point, flags | MK_MBUTTON, false, false); | 646 // Clear out-of-order release flag in case the "button released" event |
| 647 // was truly completely swallowed. |
| 648 released_buttons_out_of_order_ &= ~VK_MBUTTON; |
| 649 if (ProcessMousePressed(point, flags | MK_MBUTTON, false, false)) |
| 650 buttons_pressed_ |= VK_MBUTTON; |
| 632 } | 651 } |
| 633 | 652 |
| 634 void WidgetWin::OnMButtonUp(UINT flags, const CPoint& point) { | 653 void WidgetWin::OnMButtonUp(UINT flags, const CPoint& point) { |
| 635 ProcessMouseReleased(point, flags | MK_MBUTTON); | 654 // If we already generated the event for this button out of order, |
| 655 // avoid doing it twice. |
| 656 if (0 == (released_buttons_out_of_order_ & VK_MBUTTON)) { |
| 657 ProcessMouseReleased(point, flags | MK_MBUTTON); |
| 658 } |
| 659 released_buttons_out_of_order_ &= ~VK_MBUTTON; |
| 660 buttons_pressed_ &= ~VK_MBUTTON; |
| 636 } | 661 } |
| 637 | 662 |
| 638 void WidgetWin::OnMButtonDblClk(UINT flags, const CPoint& point) { | 663 void WidgetWin::OnMButtonDblClk(UINT flags, const CPoint& point) { |
| 639 ProcessMousePressed(point, flags | MK_MBUTTON, true, false); | 664 ProcessMousePressed(point, flags | MK_MBUTTON, true, false); |
| 640 } | 665 } |
| 641 | 666 |
| 642 LRESULT WidgetWin::OnMouseActivate(HWND window, UINT hittest_code, | 667 LRESULT WidgetWin::OnMouseActivate(HWND window, UINT hittest_code, |
| 643 UINT message) { | 668 UINT message) { |
| 644 SetMsgHandled(FALSE); | 669 SetMsgHandled(FALSE); |
| 645 return MA_ACTIVATE; | 670 return MA_ACTIVATE; |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 742 } | 767 } |
| 743 SetMsgHandled(FALSE); | 768 SetMsgHandled(FALSE); |
| 744 return 0; | 769 return 0; |
| 745 } | 770 } |
| 746 | 771 |
| 747 void WidgetWin::OnPaint(HDC dc) { | 772 void WidgetWin::OnPaint(HDC dc) { |
| 748 root_view_->OnPaint(GetNativeView()); | 773 root_view_->OnPaint(GetNativeView()); |
| 749 } | 774 } |
| 750 | 775 |
| 751 void WidgetWin::OnRButtonDown(UINT flags, const CPoint& point) { | 776 void WidgetWin::OnRButtonDown(UINT flags, const CPoint& point) { |
| 752 ProcessMousePressed(point, flags | MK_RBUTTON, false, false); | 777 // Clear out-of-order release flag in case the "button released" event |
| 778 // was truly completely swallowed. |
| 779 released_buttons_out_of_order_ &= ~right_button_code_; |
| 780 if (ProcessMousePressed(point, flags | MK_RBUTTON, false, false)) |
| 781 buttons_pressed_ |= right_button_code_; |
| 753 } | 782 } |
| 754 | 783 |
| 755 void WidgetWin::OnRButtonUp(UINT flags, const CPoint& point) { | 784 void WidgetWin::OnRButtonUp(UINT flags, const CPoint& point) { |
| 756 ProcessMouseReleased(point, flags | MK_RBUTTON); | 785 // If we already generated the event for this button out of order, |
| 786 // avoid doing it twice. |
| 787 if (0 == (released_buttons_out_of_order_ & right_button_code_)) { |
| 788 ProcessMouseReleased(point, flags | MK_RBUTTON); |
| 789 } |
| 790 released_buttons_out_of_order_ &= ~right_button_code_; |
| 791 buttons_pressed_ &= ~right_button_code_; |
| 757 } | 792 } |
| 758 | 793 |
| 759 void WidgetWin::OnRButtonDblClk(UINT flags, const CPoint& point) { | 794 void WidgetWin::OnRButtonDblClk(UINT flags, const CPoint& point) { |
| 760 ProcessMousePressed(point, flags | MK_RBUTTON, true, false); | 795 ProcessMousePressed(point, flags | MK_RBUTTON, true, false); |
| 761 } | 796 } |
| 762 | 797 |
| 763 void WidgetWin::OnSize(UINT param, const CSize& size) { | 798 void WidgetWin::OnSize(UINT param, const CSize& size) { |
| 764 ChangeSize(param, size); | 799 ChangeSize(param, size); |
| 765 } | 800 } |
| 766 | 801 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 812 if (non_client) | 847 if (non_client) |
| 813 View::ConvertPointToView(NULL, root_view_.get(), &converted_point); | 848 View::ConvertPointToView(NULL, root_view_.get(), &converted_point); |
| 814 MouseEvent mouse_pressed(Event::ET_MOUSE_PRESSED, | 849 MouseEvent mouse_pressed(Event::ET_MOUSE_PRESSED, |
| 815 converted_point.x(), | 850 converted_point.x(), |
| 816 converted_point.y(), | 851 converted_point.y(), |
| 817 (dbl_click ? MouseEvent::EF_IS_DOUBLE_CLICK : 0) | | 852 (dbl_click ? MouseEvent::EF_IS_DOUBLE_CLICK : 0) | |
| 818 (non_client ? MouseEvent::EF_IS_NON_CLIENT : 0) | | 853 (non_client ? MouseEvent::EF_IS_NON_CLIENT : 0) | |
| 819 Event::ConvertWindowsFlags(flags)); | 854 Event::ConvertWindowsFlags(flags)); |
| 820 if (root_view_->OnMousePressed(mouse_pressed)) { | 855 if (root_view_->OnMousePressed(mouse_pressed)) { |
| 821 is_mouse_down_ = true; | 856 is_mouse_down_ = true; |
| 857 gfx::Point screen_loc(point); |
| 858 View::ConvertPointToScreen(root_view_.get(), &screen_loc); |
| 859 last_mouse_move_x_ = screen_loc.x(); |
| 860 last_mouse_move_y_ = screen_loc.y(); |
| 861 last_mouse_event_was_move_ = false; |
| 822 if (!has_capture_) { | 862 if (!has_capture_) { |
| 823 SetCapture(); | 863 SetCapture(); |
| 824 has_capture_ = true; | 864 has_capture_ = true; |
| 825 } | 865 } |
| 826 return true; | 866 return true; |
| 827 } | 867 } |
| 828 return false; | 868 return false; |
| 829 } | 869 } |
| 830 | 870 |
| 831 void WidgetWin::ProcessMouseDragged(const CPoint& point, UINT flags) { | 871 void WidgetWin::ProcessMouseDragged(const CPoint& point, UINT flags) { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 848 if (has_capture_ && ReleaseCaptureOnMouseReleased()) { | 888 if (has_capture_ && ReleaseCaptureOnMouseReleased()) { |
| 849 has_capture_ = false; | 889 has_capture_ = false; |
| 850 ReleaseCapture(); | 890 ReleaseCapture(); |
| 851 } | 891 } |
| 852 is_mouse_down_ = false; | 892 is_mouse_down_ = false; |
| 853 root_view_->OnMouseReleased(mouse_up, false); | 893 root_view_->OnMouseReleased(mouse_up, false); |
| 854 } | 894 } |
| 855 | 895 |
| 856 void WidgetWin::ProcessMouseMoved(const CPoint &point, UINT flags, | 896 void WidgetWin::ProcessMouseMoved(const CPoint &point, UINT flags, |
| 857 bool is_nonclient) { | 897 bool is_nonclient) { |
| 898 // Under heavy load it may happen that a mouse release event gets |
| 899 // "swallowed" or postponed. Explicitely check mouse button state here |
| 900 // to make sure this hasn't happened. |
| 901 CheckOutOfOrderMouseButtonRelease(left_button_code_); |
| 902 CheckOutOfOrderMouseButtonRelease(VK_MBUTTON); |
| 903 CheckOutOfOrderMouseButtonRelease(right_button_code_); |
| 858 // Windows only fires WM_MOUSELEAVE events if the application begins | 904 // Windows only fires WM_MOUSELEAVE events if the application begins |
| 859 // "tracking" mouse events for a given HWND during WM_MOUSEMOVE events. | 905 // "tracking" mouse events for a given HWND during WM_MOUSEMOVE events. |
| 860 // We need to call |TrackMouseEvents| to listen for WM_MOUSELEAVE. | 906 // We need to call |TrackMouseEvents| to listen for WM_MOUSELEAVE. |
| 861 if (!has_capture_) | 907 if (!has_capture_) |
| 862 TrackMouseEvents(is_nonclient ? TME_NONCLIENT | TME_LEAVE : TME_LEAVE); | 908 TrackMouseEvents(is_nonclient ? TME_NONCLIENT | TME_LEAVE : TME_LEAVE); |
| 909 |
| 910 gfx::Point screen_loc(point); |
| 911 View::ConvertPointToScreen(root_view_.get(), &screen_loc); |
| 863 if (has_capture_ && is_mouse_down_) { | 912 if (has_capture_ && is_mouse_down_) { |
| 864 ProcessMouseDragged(point, flags); | 913 ProcessMouseDragged(point, flags); |
| 865 } else { | 914 } else { |
| 866 gfx::Point screen_loc(point); | |
| 867 View::ConvertPointToScreen(root_view_.get(), &screen_loc); | |
| 868 if (last_mouse_event_was_move_ && last_mouse_move_x_ == screen_loc.x() && | 915 if (last_mouse_event_was_move_ && last_mouse_move_x_ == screen_loc.x() && |
| 869 last_mouse_move_y_ == screen_loc.y()) { | 916 last_mouse_move_y_ == screen_loc.y()) { |
| 870 // Don't generate a mouse event for the same location as the last. | 917 // Don't generate a mouse event for the same location as the last. |
| 871 return; | 918 return; |
| 872 } | 919 } |
| 873 last_mouse_move_x_ = screen_loc.x(); | |
| 874 last_mouse_move_y_ = screen_loc.y(); | |
| 875 last_mouse_event_was_move_ = true; | 920 last_mouse_event_was_move_ = true; |
| 876 MouseEvent mouse_move(Event::ET_MOUSE_MOVED, | 921 MouseEvent mouse_move(Event::ET_MOUSE_MOVED, |
| 877 point.x, | 922 point.x, |
| 878 point.y, | 923 point.y, |
| 879 Event::ConvertWindowsFlags(flags)); | 924 Event::ConvertWindowsFlags(flags)); |
| 880 root_view_->OnMouseMoved(mouse_move); | 925 root_view_->OnMouseMoved(mouse_move); |
| 881 } | 926 } |
| 927 last_mouse_move_x_ = screen_loc.x(); |
| 928 last_mouse_move_y_ = screen_loc.y(); |
| 882 } | 929 } |
| 883 | 930 |
| 884 void WidgetWin::ProcessMouseExited() { | 931 void WidgetWin::ProcessMouseExited() { |
| 885 last_mouse_event_was_move_ = false; | 932 last_mouse_event_was_move_ = false; |
| 886 root_view_->ProcessOnMouseExited(); | 933 root_view_->ProcessOnMouseExited(); |
| 887 // Reset our tracking flag so that future mouse movement over this WidgetWin | 934 // Reset our tracking flag so that future mouse movement over this WidgetWin |
| 888 // results in a new tracking session. | 935 // results in a new tracking session. |
| 889 active_mouse_tracking_flags_ = 0; | 936 active_mouse_tracking_flags_ = 0; |
| 890 } | 937 } |
| 891 | 938 |
| 939 void WidgetWin::CheckOutOfOrderMouseButtonRelease(int code) { |
| 940 SHORT key_state = ::GetAsyncKeyState(code); |
| 941 if ((0 == (key_state & 0x8000)) && |
| 942 (0 != (buttons_pressed_ & code))) { |
| 943 // left button was released in the meantime |
| 944 // generate an out-of-order event for this, at the last recorded position |
| 945 CPoint pt(last_mouse_move_x_, last_mouse_move_y_); |
| 946 ProcessMouseReleased(pt, code); |
| 947 released_buttons_out_of_order_ |= code; |
| 948 buttons_pressed_ &= ~code; |
| 949 } |
| 950 } |
| 951 |
| 892 void WidgetWin::ChangeSize(UINT size_param, const CSize& size) { | 952 void WidgetWin::ChangeSize(UINT size_param, const CSize& size) { |
| 893 CRect rect; | 953 CRect rect; |
| 894 if (use_layered_buffer_) { | 954 if (use_layered_buffer_) { |
| 895 GetWindowRect(&rect); | 955 GetWindowRect(&rect); |
| 896 SizeContents(rect); | 956 SizeContents(rect); |
| 897 } else { | 957 } else { |
| 898 GetClientRect(&rect); | 958 GetClientRect(&rect); |
| 899 } | 959 } |
| 900 | 960 |
| 901 // Resizing changes the size of the view hierarchy and thus forces a | 961 // Resizing changes the size of the view hierarchy and thus forces a |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1082 } | 1142 } |
| 1083 if (WA_INACTIVE == activation_state) { | 1143 if (WA_INACTIVE == activation_state) { |
| 1084 widget->focus_manager_->StoreFocusedView(); | 1144 widget->focus_manager_->StoreFocusedView(); |
| 1085 } else { | 1145 } else { |
| 1086 // We must restore the focus after the message has been DefProc'ed as it | 1146 // We must restore the focus after the message has been DefProc'ed as it |
| 1087 // does set the focus to the last focused HWND. | 1147 // does set the focus to the last focused HWND. |
| 1088 widget->focus_manager_->RestoreFocusedView(); | 1148 widget->focus_manager_->RestoreFocusedView(); |
| 1089 } | 1149 } |
| 1090 } | 1150 } |
| 1091 } // namespace views | 1151 } // namespace views |
| OLD | NEW |