| Index: views/widget/widget_win.cc
|
| ===================================================================
|
| --- views/widget/widget_win.cc (revision 20614)
|
| +++ views/widget/widget_win.cc (working copy)
|
| @@ -144,10 +144,15 @@
|
| delete_on_destroy_(true),
|
| can_update_layered_window_(true),
|
| last_mouse_event_was_move_(false),
|
| + mouse_buttons_are_swapped_(0 != GetSystemMetrics(SM_SWAPBUTTON)),
|
| + buttons_pressed_(0),
|
| + released_buttons_out_of_order_(0),
|
| is_mouse_down_(false),
|
| is_window_(false),
|
| class_style_(CS_DBLCLKS),
|
| hwnd_(NULL) {
|
| + left_button_code_ = mouse_buttons_are_swapped_ ? VK_RBUTTON : VK_LBUTTON;
|
| + right_button_code_ = mouse_buttons_are_swapped_ ? VK_LBUTTON : VK_RBUTTON;
|
| }
|
|
|
| WidgetWin::~WidgetWin() {
|
| @@ -616,11 +621,21 @@
|
| }
|
|
|
| void WidgetWin::OnLButtonDown(UINT flags, const CPoint& point) {
|
| - ProcessMousePressed(point, flags | MK_LBUTTON, false, false);
|
| + // Clear out-of-order release flag in case the "button released" event
|
| + // was truly completely swallowed.
|
| + released_buttons_out_of_order_ &= ~left_button_code_;
|
| + if (ProcessMousePressed(point, flags | MK_LBUTTON, false, false))
|
| + buttons_pressed_ |= left_button_code_;
|
| }
|
|
|
| void WidgetWin::OnLButtonUp(UINT flags, const CPoint& point) {
|
| - ProcessMouseReleased(point, flags | MK_LBUTTON);
|
| + // If we already generated the event for this button out of order,
|
| + // avoid doing it twice.
|
| + if (0 == (released_buttons_out_of_order_ & left_button_code_)) {
|
| + ProcessMouseReleased(point, flags | MK_LBUTTON);
|
| + }
|
| + released_buttons_out_of_order_ &= ~left_button_code_;
|
| + buttons_pressed_ &= ~left_button_code_;
|
| }
|
|
|
| void WidgetWin::OnLButtonDblClk(UINT flags, const CPoint& point) {
|
| @@ -628,11 +643,21 @@
|
| }
|
|
|
| void WidgetWin::OnMButtonDown(UINT flags, const CPoint& point) {
|
| - ProcessMousePressed(point, flags | MK_MBUTTON, false, false);
|
| + // Clear out-of-order release flag in case the "button released" event
|
| + // was truly completely swallowed.
|
| + released_buttons_out_of_order_ &= ~VK_MBUTTON;
|
| + if (ProcessMousePressed(point, flags | MK_MBUTTON, false, false))
|
| + buttons_pressed_ |= VK_MBUTTON;
|
| }
|
|
|
| void WidgetWin::OnMButtonUp(UINT flags, const CPoint& point) {
|
| - ProcessMouseReleased(point, flags | MK_MBUTTON);
|
| + // If we already generated the event for this button out of order,
|
| + // avoid doing it twice.
|
| + if (0 == (released_buttons_out_of_order_ & VK_MBUTTON)) {
|
| + ProcessMouseReleased(point, flags | MK_MBUTTON);
|
| + }
|
| + released_buttons_out_of_order_ &= ~VK_MBUTTON;
|
| + buttons_pressed_ &= ~VK_MBUTTON;
|
| }
|
|
|
| void WidgetWin::OnMButtonDblClk(UINT flags, const CPoint& point) {
|
| @@ -749,11 +774,21 @@
|
| }
|
|
|
| void WidgetWin::OnRButtonDown(UINT flags, const CPoint& point) {
|
| - ProcessMousePressed(point, flags | MK_RBUTTON, false, false);
|
| + // Clear out-of-order release flag in case the "button released" event
|
| + // was truly completely swallowed.
|
| + released_buttons_out_of_order_ &= ~right_button_code_;
|
| + if (ProcessMousePressed(point, flags | MK_RBUTTON, false, false))
|
| + buttons_pressed_ |= right_button_code_;
|
| }
|
|
|
| void WidgetWin::OnRButtonUp(UINT flags, const CPoint& point) {
|
| - ProcessMouseReleased(point, flags | MK_RBUTTON);
|
| + // If we already generated the event for this button out of order,
|
| + // avoid doing it twice.
|
| + if (0 == (released_buttons_out_of_order_ & right_button_code_)) {
|
| + ProcessMouseReleased(point, flags | MK_RBUTTON);
|
| + }
|
| + released_buttons_out_of_order_ &= ~right_button_code_;
|
| + buttons_pressed_ &= ~right_button_code_;
|
| }
|
|
|
| void WidgetWin::OnRButtonDblClk(UINT flags, const CPoint& point) {
|
| @@ -819,6 +854,11 @@
|
| Event::ConvertWindowsFlags(flags));
|
| if (root_view_->OnMousePressed(mouse_pressed)) {
|
| is_mouse_down_ = true;
|
| + gfx::Point screen_loc(point);
|
| + View::ConvertPointToScreen(root_view_.get(), &screen_loc);
|
| + last_mouse_move_x_ = screen_loc.x();
|
| + last_mouse_move_y_ = screen_loc.y();
|
| + last_mouse_event_was_move_ = false;
|
| if (!has_capture_) {
|
| SetCapture();
|
| has_capture_ = true;
|
| @@ -855,23 +895,28 @@
|
|
|
| void WidgetWin::ProcessMouseMoved(const CPoint &point, UINT flags,
|
| bool is_nonclient) {
|
| + // Under heavy load it may happen that a mouse release event gets
|
| + // "swallowed" or postponed. Explicitely check mouse button state here
|
| + // to make sure this hasn't happened.
|
| + CheckOutOfOrderMouseButtonRelease(left_button_code_);
|
| + CheckOutOfOrderMouseButtonRelease(VK_MBUTTON);
|
| + CheckOutOfOrderMouseButtonRelease(right_button_code_);
|
| // Windows only fires WM_MOUSELEAVE events if the application begins
|
| // "tracking" mouse events for a given HWND during WM_MOUSEMOVE events.
|
| // We need to call |TrackMouseEvents| to listen for WM_MOUSELEAVE.
|
| if (!has_capture_)
|
| TrackMouseEvents(is_nonclient ? TME_NONCLIENT | TME_LEAVE : TME_LEAVE);
|
| +
|
| + gfx::Point screen_loc(point);
|
| + View::ConvertPointToScreen(root_view_.get(), &screen_loc);
|
| if (has_capture_ && is_mouse_down_) {
|
| ProcessMouseDragged(point, flags);
|
| } else {
|
| - gfx::Point screen_loc(point);
|
| - View::ConvertPointToScreen(root_view_.get(), &screen_loc);
|
| if (last_mouse_event_was_move_ && last_mouse_move_x_ == screen_loc.x() &&
|
| last_mouse_move_y_ == screen_loc.y()) {
|
| // Don't generate a mouse event for the same location as the last.
|
| return;
|
| }
|
| - last_mouse_move_x_ = screen_loc.x();
|
| - last_mouse_move_y_ = screen_loc.y();
|
| last_mouse_event_was_move_ = true;
|
| MouseEvent mouse_move(Event::ET_MOUSE_MOVED,
|
| point.x,
|
| @@ -879,6 +924,8 @@
|
| Event::ConvertWindowsFlags(flags));
|
| root_view_->OnMouseMoved(mouse_move);
|
| }
|
| + last_mouse_move_x_ = screen_loc.x();
|
| + last_mouse_move_y_ = screen_loc.y();
|
| }
|
|
|
| void WidgetWin::ProcessMouseExited() {
|
| @@ -889,6 +936,19 @@
|
| active_mouse_tracking_flags_ = 0;
|
| }
|
|
|
| +void WidgetWin::CheckOutOfOrderMouseButtonRelease(int code) {
|
| + SHORT key_state = ::GetAsyncKeyState(code);
|
| + if ((0 == (key_state & 0x8000)) &&
|
| + (0 != (buttons_pressed_ & code))) {
|
| + // left button was released in the meantime
|
| + // generate an out-of-order event for this, at the last recorded position
|
| + CPoint pt(last_mouse_move_x_, last_mouse_move_y_);
|
| + ProcessMouseReleased(pt, code);
|
| + released_buttons_out_of_order_ |= code;
|
| + buttons_pressed_ &= ~code;
|
| + }
|
| +}
|
| +
|
| void WidgetWin::ChangeSize(UINT size_param, const CSize& size) {
|
| CRect rect;
|
| if (use_layered_buffer_) {
|
|
|