Commit bddf8dd3 authored by tdanderson's avatar tdanderson Committed by Commit bot

Do not interchange MOUSE_MOVED and MOUSE_DRAGGED events in Widget

In Widget::OnMouseEvent(), do not handle MOUSE_MOVED
events as MOUSE_DRAGGED events, and do not handle
MOUSE_DRAGGED events as MOUSE_MOVED events; instead
trust that the mouse event type has been set correctly
before arriving at Widget. This also allows us to
remove the member |is_mouse_button_pressed_|
from Widget.

BUG=412929, 412931
TEST=WidgetTest.DragIntoView, WidgetTest.DragOutOfView

Review URL: https://codereview.chromium.org/560053002

Cr-Commit-Position: refs/heads/master@{#297215}
parent 514a30a4
......@@ -368,7 +368,7 @@ TEST_F(ViewTest, MouseEvent) {
v2->Reset();
ui::MouseEvent released(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(), 0,
0);
root->OnMouseDragged(released);
root->OnMouseReleased(released);
EXPECT_EQ(v2->last_mouse_event_type_, ui::ET_MOUSE_RELEASED);
EXPECT_EQ(v2->location_.x(), -100);
EXPECT_EQ(v2->location_.y(), -100);
......
......@@ -429,6 +429,7 @@ bool RootView::OnMousePressed(const ui::MouseEvent& event) {
}
bool RootView::OnMouseDragged(const ui::MouseEvent& event) {
CHECK_EQ(ui::ET_MOUSE_DRAGGED, event.type());
if (mouse_pressed_handler_) {
SetMouseLocationAndFlags(event);
......@@ -486,6 +487,7 @@ void RootView::OnMouseCaptureLost() {
}
void RootView::OnMouseMoved(const ui::MouseEvent& event) {
CHECK_EQ(ui::ET_MOUSE_MOVED, event.type());
View* v = GetEventHandlerForPoint(event.location());
// Find the first enabled view, or the existing move handler, whichever comes
// first. The check for the existing handler is because if a view becomes
......
......@@ -168,7 +168,6 @@ Widget::Widget()
is_top_level_(false),
native_widget_initialized_(false),
native_widget_destroyed_(false),
is_mouse_button_pressed_(false),
ignore_capture_loss_(false),
last_mouse_event_was_move_(false),
auto_release_capture_(true),
......@@ -351,10 +350,6 @@ void Widget::Init(const InitParams& in_params) {
AsNativeWidgetPrivate();
root_view_.reset(CreateRootView());
default_theme_provider_.reset(new ui::DefaultThemeProvider);
if (params.type == InitParams::TYPE_MENU) {
is_mouse_button_pressed_ =
internal::NativeWidgetPrivate::IsMouseButtonDown();
}
native_widget_->InitNativeWidget(params);
if (RequiresNonClientView(params.type)) {
non_client_view_ = new NonClientView;
......@@ -948,8 +943,6 @@ void Widget::SetCapture(View* view) {
return;
}
if (internal::NativeWidgetPrivate::IsMouseButtonDown())
is_mouse_button_pressed_ = true;
root_view_->SetMouseHandler(view);
}
......@@ -1190,11 +1183,12 @@ void Widget::OnKeyEvent(ui::KeyEvent* event) {
// RootView from anywhere in Widget. Use
// SendEventToProcessor() instead. See crbug.com/348087.
void Widget::OnMouseEvent(ui::MouseEvent* event) {
if (event->type() != ui::ET_MOUSE_MOVED)
last_mouse_event_was_move_ = false;
View* root_view = GetRootView();
switch (event->type()) {
case ui::ET_MOUSE_PRESSED: {
last_mouse_event_was_move_ = false;
// We may get deleted by the time we return from OnMousePressed. So we
// use an observer to make sure we are still alive.
WidgetDeletionObserver widget_deletion_observer(this);
......@@ -1212,7 +1206,6 @@ void Widget::OnMouseEvent(ui::MouseEvent* event) {
if (root_view && root_view->OnMousePressed(*event) &&
widget_deletion_observer.IsWidgetAlive() && IsVisible() &&
internal::NativeWidgetPrivate::IsMouseButtonDown()) {
is_mouse_button_pressed_ = true;
if (!native_widget_->HasCapture())
native_widget_->SetCapture();
event->SetHandled();
......@@ -1221,8 +1214,6 @@ void Widget::OnMouseEvent(ui::MouseEvent* event) {
}
case ui::ET_MOUSE_RELEASED:
last_mouse_event_was_move_ = false;
is_mouse_button_pressed_ = false;
// Release capture first, to avoid confusion if OnMouseReleased blocks.
if (auto_release_capture_ && native_widget_->HasCapture()) {
base::AutoReset<bool> resetter(&ignore_capture_loss_, true);
......@@ -1235,13 +1226,8 @@ void Widget::OnMouseEvent(ui::MouseEvent* event) {
return;
case ui::ET_MOUSE_MOVED:
case ui::ET_MOUSE_DRAGGED:
if (native_widget_->HasCapture() && is_mouse_button_pressed_) {
last_mouse_event_was_move_ = false;
if (root_view)
root_view->OnMouseDragged(*event);
} else if (!last_mouse_event_was_move_ ||
last_mouse_event_position_ != event->location()) {
if (!last_mouse_event_was_move_ ||
last_mouse_event_position_ != event->location()) {
last_mouse_event_position_ = event->location();
last_mouse_event_was_move_ = true;
if (root_view)
......@@ -1249,8 +1235,12 @@ void Widget::OnMouseEvent(ui::MouseEvent* event) {
}
return;
case ui::ET_MOUSE_DRAGGED:
if (root_view)
root_view->OnMouseDragged(*event);
return;
case ui::ET_MOUSE_EXITED:
last_mouse_event_was_move_ = false;
if (root_view)
root_view->OnMouseExited(*event);
return;
......@@ -1273,7 +1263,6 @@ void Widget::OnMouseCaptureLost() {
View* root_view = GetRootView();
if (root_view)
root_view->OnMouseCaptureLost();
is_mouse_button_pressed_ = false;
}
void Widget::OnScrollEvent(ui::ScrollEvent* event) {
......
......@@ -920,17 +920,13 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
// Whether native widget has been destroyed.
bool native_widget_destroyed_;
// TODO(beng): Remove NativeWidgetGtk's dependence on these:
// If true, the mouse is currently down.
bool is_mouse_button_pressed_;
// True if capture losses should be ignored.
bool ignore_capture_loss_;
// TODO(beng): Remove NativeWidgetGtk's dependence on these:
// The following are used to detect duplicate mouse move events and not
// deliver them. Displaying a window may result in the system generating
// duplicate move events even though the mouse hasn't moved.
// TODO(tdanderson): We may be able to remove these members.
bool last_mouse_event_was_move_;
gfx::Point last_mouse_event_position_;
......
......@@ -3193,6 +3193,84 @@ TEST_F(WidgetTest, MouseEventTypesViaGenerator) {
widget->CloseNow();
}
// Tests that a view does not receive entered, dragged, or moved events if
// a mouse cursor is moved into it while the left mouse button is pressed.
TEST_F(WidgetTest, DragIntoView) {
EventCountView* container = new EventCountView;
container->SetBounds(0, 0, 100, 80);
EventCountView* consume_view = new EventCountView;
consume_view->set_handle_mode(EventCountView::CONSUME_EVENTS);
consume_view->SetBounds(10, 10, 50, 40);
Widget* widget = CreateTopLevelFramelessPlatformWidget();
widget->SetBounds(gfx::Rect(0, 0, 100, 80));
widget->SetContentsView(container);
container->AddChildView(consume_view);
widget->Show();
ui::test::EventGenerator generator(GetContext(), widget->GetNativeWindow());
generator.set_current_location(gfx::Point(75, 15));
generator.PressLeftButton();
generator.MoveMouseTo(gfx::Point(20, 20));
EXPECT_EQ(0, consume_view->GetEventCount(ui::ET_MOUSE_ENTERED));
EXPECT_EQ(0, consume_view->GetEventCount(ui::ET_MOUSE_DRAGGED));
EXPECT_EQ(0, consume_view->GetEventCount(ui::ET_MOUSE_MOVED));
widget->CloseNow();
}
// Tests that a view receives the correct mouse events if a mouse cursor
// is moved out of its bounds while the left mouse button is pressed.
TEST_F(WidgetTest, DragOutOfView) {
EventCountView* container = new EventCountView;
container->SetBounds(0, 0, 100, 80);
EventCountView* consume_view = new EventCountView;
consume_view->set_handle_mode(EventCountView::CONSUME_EVENTS);
consume_view->SetBounds(10, 10, 50, 40);
Widget* widget = CreateTopLevelFramelessPlatformWidget();
widget->SetBounds(gfx::Rect(0, 0, 100, 80));
widget->SetContentsView(container);
container->AddChildView(consume_view);
widget->Show();
ui::test::EventGenerator generator(GetContext(), widget->GetNativeWindow());
generator.set_current_location(gfx::Point(20, 20));
generator.PressLeftButton();
EXPECT_EQ(1, consume_view->GetEventCount(ui::ET_MOUSE_PRESSED));
EXPECT_EQ(0, container->GetEventCount(ui::ET_MOUSE_PRESSED));
consume_view->ResetCounts();
generator.MoveMouseTo(gfx::Point(70, 70));
EXPECT_EQ(0, consume_view->GetEventCount(ui::ET_MOUSE_EXITED));
EXPECT_EQ(1, consume_view->GetEventCount(ui::ET_MOUSE_DRAGGED));
EXPECT_EQ(0, consume_view->GetEventCount(ui::ET_MOUSE_MOVED));
EXPECT_EQ(0, container->GetEventCount(ui::ET_MOUSE_ENTERED));
EXPECT_EQ(0, container->GetEventCount(ui::ET_MOUSE_DRAGGED));
EXPECT_EQ(0, container->GetEventCount(ui::ET_MOUSE_MOVED));
consume_view->ResetCounts();
generator.MoveMouseTo(gfx::Point(71, 71));
EXPECT_EQ(1, consume_view->GetEventCount(ui::ET_MOUSE_DRAGGED));
EXPECT_EQ(0, consume_view->GetEventCount(ui::ET_MOUSE_MOVED));
EXPECT_EQ(0, container->GetEventCount(ui::ET_MOUSE_DRAGGED));
EXPECT_EQ(0, container->GetEventCount(ui::ET_MOUSE_MOVED));
consume_view->ResetCounts();
generator.ReleaseLeftButton();
EXPECT_EQ(1, consume_view->GetEventCount(ui::ET_MOUSE_RELEASED));
EXPECT_EQ(0, container->GetEventCount(ui::ET_MOUSE_RELEASED));
consume_view->ResetCounts();
widget->CloseNow();
}
// Tests that the root view is correctly set up for Widget types that do not
// require a non-client view, before any other views are added to the widget.
// That is, before Widget::ReorderNativeViews() is called which, if called with
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment