diff options
-rw-r--r-- | ash/wm/partial_screenshot_view.cc | 2 | ||||
-rw-r--r-- | content/browser/renderer_host/render_widget_host_view_aura.cc | 4 | ||||
-rw-r--r-- | ui/aura/gestures/gesture_recognizer_unittest.cc | 29 | ||||
-rw-r--r-- | ui/aura/root_window.cc | 154 | ||||
-rw-r--r-- | ui/aura/root_window.h | 18 | ||||
-rw-r--r-- | ui/aura/root_window_host_linux.cc | 2 | ||||
-rw-r--r-- | ui/aura/root_window_host_win.cc | 2 | ||||
-rw-r--r-- | ui/aura/root_window_unittest.cc | 55 | ||||
-rw-r--r-- | ui/aura/window.cc | 10 | ||||
-rw-r--r-- | ui/aura/window.h | 15 | ||||
-rw-r--r-- | ui/aura/window_unittest.cc | 77 | ||||
-rw-r--r-- | ui/base/events.h | 5 | ||||
-rw-r--r-- | ui/base/gestures/gesture_recognizer_impl.cc | 4 | ||||
-rw-r--r-- | ui/base/gestures/gesture_types.h | 3 | ||||
-rw-r--r-- | ui/views/controls/menu/menu_host.cc | 5 | ||||
-rw-r--r-- | ui/views/widget/native_widget_aura.cc | 10 | ||||
-rw-r--r-- | ui/views/widget/native_widget_aura.h | 4 | ||||
-rw-r--r-- | ui/views/widget/native_widget_private.h | 14 | ||||
-rw-r--r-- | ui/views/widget/native_widget_win.cc | 18 | ||||
-rw-r--r-- | ui/views/widget/native_widget_win.h | 5 | ||||
-rw-r--r-- | ui/views/widget/widget.cc | 15 | ||||
-rw-r--r-- | ui/views/widget/widget_unittest.cc | 12 |
22 files changed, 251 insertions, 212 deletions
diff --git a/ash/wm/partial_screenshot_view.cc b/ash/wm/partial_screenshot_view.cc index ce5a68f..1415441 100644 --- a/ash/wm/partial_screenshot_view.cc +++ b/ash/wm/partial_screenshot_view.cc @@ -59,7 +59,7 @@ void PartialScreenshotView::StartPartialScreenshot( widget->Show(); // Captures mouse events in case that context menu already captures the // events. This will close the context menu. - widget->GetNativeView()->SetCapture(); + widget->GetNativeView()->SetCapture(ui::CW_LOCK_MOUSE | ui::CW_LOCK_TOUCH); view->set_window(widget->GetNativeWindow()); Shell::GetInstance()->partial_screenshot_filter()->Activate(view); diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc index 0d16c71..53084ff 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc @@ -682,7 +682,7 @@ bool RenderWidgetHostViewAura::LockMouse() { mouse_locked_ = true; - root_window->SetCapture(window_); + root_window->SetCapture(window_, ui::CW_LOCK_MOUSE); if (root_window->ConfineCursorToWindow()) { root_window->ShowCursor(false); synthetic_move_sent_ = true; @@ -1014,7 +1014,7 @@ bool RenderWidgetHostViewAura::OnMouseEvent(aura::MouseEvent* event) { switch (event->type()) { case ui::ET_MOUSE_PRESSED: - window_->SetCapture(); + window_->SetCapture(ui::CW_LOCK_MOUSE); // Confirm existing composition text on mouse click events, to make sure // the input caret won't be moved with an ongoing composition text. FinishImeCompositionSession(); diff --git a/ui/aura/gestures/gesture_recognizer_unittest.cc b/ui/aura/gestures/gesture_recognizer_unittest.cc index 863041b..20ff390 100644 --- a/ui/aura/gestures/gesture_recognizer_unittest.cc +++ b/ui/aura/gestures/gesture_recognizer_unittest.cc @@ -3,7 +3,6 @@ // found in the LICENSE file. #include "base/memory/scoped_vector.h" -#include "base/string_number_conversions.h" #include "base/timer.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/aura/event.h" @@ -24,11 +23,6 @@ namespace test { namespace { -std::string WindowIDAsString(ui::GestureConsumer* consumer) { - return consumer && !consumer->ignores_events() ? - base::IntToString(static_cast<Window*>(consumer)->id()) : "?"; -} - // A delegate that keeps track of gesture events. class GestureEventConsumeDelegate : public TestWindowDelegate { public: @@ -929,17 +923,17 @@ TEST_F(GestureRecognizerTest, GestureTapSyntheticMouse) { EXPECT_TRUE(delegate->mouse_enter()); EXPECT_TRUE(delegate->mouse_press()); EXPECT_TRUE(delegate->mouse_release()); - EXPECT_FALSE(delegate->mouse_exit()); + EXPECT_TRUE(delegate->mouse_exit()); EXPECT_FALSE(delegate->double_click()); delegate->Reset(); GestureEvent tap2(ui::ET_GESTURE_DOUBLE_TAP, 20, 20, 0, base::Time::Now(), 0, 0, 1 << kTouchId); root_window()->DispatchGestureEvent(&tap2); - EXPECT_FALSE(delegate->mouse_enter()); + EXPECT_TRUE(delegate->mouse_enter()); EXPECT_TRUE(delegate->mouse_press()); EXPECT_TRUE(delegate->mouse_release()); - EXPECT_FALSE(delegate->mouse_exit()); + EXPECT_TRUE(delegate->mouse_exit()); EXPECT_TRUE(delegate->double_click()); } @@ -1403,7 +1397,6 @@ TEST_F(GestureRecognizerTest, GestureEventTouchLockSelectsCorrectWindow) { delegates[i] = new GestureEventConsumeDelegate(); windows[i] = CreateTestWindowWithDelegate( delegates[i], i, *window_bounds[i], NULL); - windows[i]->set_id(i); TouchEvent press(ui::ET_TOUCH_PRESSED, window_bounds[i]->origin(), i, GetTime()); root_window()->DispatchTouchEvent(&press); @@ -1412,13 +1405,13 @@ TEST_F(GestureRecognizerTest, GestureEventTouchLockSelectsCorrectWindow) { // Touches should now be associated with the closest touch within // ui::GestureConfiguration::max_separation_for_gesture_touches_in_pixels target = gesture_recognizer->GetTargetForLocation(gfx::Point(11, 11)); - EXPECT_EQ("0", WindowIDAsString(target)); + EXPECT_EQ(windows[0], target); target = gesture_recognizer->GetTargetForLocation(gfx::Point(511, 11)); - EXPECT_EQ("1", WindowIDAsString(target)); + EXPECT_EQ(windows[1], target); target = gesture_recognizer->GetTargetForLocation(gfx::Point(11, 511)); - EXPECT_EQ("2", WindowIDAsString(target)); + EXPECT_EQ(windows[2], target); target = gesture_recognizer->GetTargetForLocation(gfx::Point(511, 511)); - EXPECT_EQ("3", WindowIDAsString(target)); + EXPECT_EQ(windows[3], target); // Add a touch in the middle associated with windows[2] TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(0, 500), @@ -1429,16 +1422,16 @@ TEST_F(GestureRecognizerTest, GestureEventTouchLockSelectsCorrectWindow) { root_window()->DispatchTouchEvent(&move); target = gesture_recognizer->GetTargetForLocation(gfx::Point(250, 250)); - EXPECT_EQ("2", WindowIDAsString(target)); + EXPECT_EQ(windows[2], target); // Make sure that ties are broken by distance to a current touch // Closer to the point in the bottom right. target = gesture_recognizer->GetTargetForLocation(gfx::Point(380, 380)); - EXPECT_EQ("3", WindowIDAsString(target)); + EXPECT_EQ(windows[3], target); // This touch is closer to the point in the middle target = gesture_recognizer->GetTargetForLocation(gfx::Point(300, 300)); - EXPECT_EQ("2", WindowIDAsString(target)); + EXPECT_EQ(windows[2], target); // A touch too far from other touches won't be locked to anything target = gesture_recognizer->GetTargetForLocation(gfx::Point(1000, 1000)); @@ -1450,7 +1443,7 @@ TEST_F(GestureRecognizerTest, GestureEventTouchLockSelectsCorrectWindow) { root_window()->DispatchTouchEvent(&move2); target = gesture_recognizer->GetTargetForLocation(gfx::Point(1000, 1000)); - EXPECT_EQ("2", WindowIDAsString(target)); + EXPECT_EQ(windows[2], target); } // Check that touch events outside the root window are still handled diff --git a/ui/aura/root_window.cc b/ui/aura/root_window.cc index ad3d3ef..48a202e 100644 --- a/ui/aura/root_window.cc +++ b/ui/aura/root_window.cc @@ -39,20 +39,20 @@ namespace aura { namespace { -// These are the mouse events generated when a gesture goes unprocessed. const ui::EventType kScrollBeginTypes[] = { - ui::ET_MOUSE_PRESSED, ui::ET_MOUSE_DRAGGED, ui::ET_UNKNOWN }; + ui::ET_MOUSE_ENTERED, ui::ET_MOUSE_PRESSED, ui::ET_MOUSE_DRAGGED, + ui::ET_UNKNOWN }; const ui::EventType kScrollEndTypes[] = { - ui::ET_MOUSE_DRAGGED, ui::ET_MOUSE_RELEASED, ui::ET_UNKNOWN }; + ui::ET_MOUSE_DRAGGED, ui::ET_MOUSE_RELEASED, ui::ET_MOUSE_EXITED, + ui::ET_UNKNOWN }; const ui::EventType kScrollUpdateTypes[] = { ui::ET_MOUSE_DRAGGED, ui::ET_UNKNOWN }; const ui::EventType kTapTypes[] = { - ui::ET_MOUSE_PRESSED, ui::ET_MOUSE_RELEASED, ui::ET_UNKNOWN }; - -const int kCompositorLockTimeoutMs = 67; + ui::ET_MOUSE_ENTERED, ui::ET_MOUSE_PRESSED, ui::ET_MOUSE_RELEASED, + ui::ET_MOUSE_EXITED, ui::ET_UNKNOWN }; // Returns true if |target| has a non-client (frame) component at |location|, // in window coordinates. @@ -78,10 +78,7 @@ float GetDeviceScaleFactorFromMonitor(const aura::Window* window) { return monitor_manager->GetMonitorNearestWindow(window).device_scale_factor(); } -Window* ConsumerToWindow(ui::GestureConsumer* consumer) { - return consumer && !consumer->ignores_events() ? - static_cast<Window*>(consumer) : NULL; -} +const int kCompositorLockTimeoutMs = 67; } // namespace @@ -123,6 +120,7 @@ RootWindow::RootWindow(const gfx::Rect& initial_bounds) focused_window_(NULL), ALLOW_THIS_IN_INITIALIZER_LIST( gesture_recognizer_(ui::GestureRecognizer::Create(this))), + capture_window_flags_(0), synthesize_mouse_move_(false), waiting_on_compositing_end_(false), draw_on_compositing_end_(false), @@ -320,54 +318,65 @@ bool RootWindow::DispatchTouchEvent(TouchEvent* event) { event->UpdateForRootTransform(layer()->transform()); } bool handled = false; + + GestureConsumer* consumer = gesture_recognizer_->GetTouchLockedTarget(event); ui::TouchStatus status = ui::TOUCH_STATUS_UNKNOWN; - Window* target = capture_window_; - if (!target) { - target = ConsumerToWindow( - gesture_recognizer_->GetTouchLockedTarget(event)); + + if (!consumer || !consumer->ignores_events()) { + Window* target = static_cast<Window*>(consumer); + + if (!target && HasCapture(capture_window_, ui::CW_LOCK_TOUCH)) + target = capture_window_; + if (!target) { - target = ConsumerToWindow( + target = static_cast<Window*>( gesture_recognizer_->GetTargetForLocation(event->GetLocation())); } - } - if (!target && !bounds().Contains(event->location())) { - // If the initial touch is outside the root window, target the root. - target = this; - } else { - // We only come here when the first contact was within the root window. - if (!target) { - target = GetEventHandlerForPoint(event->location()); + if (!target && !bounds().Contains(event->location())) { + // If the touch is outside the root window, set its target to the + // root window. + target = this; + } else { + // We only come here when the first contact was within the root window. + if (!target) + target = GetEventHandlerForPoint(event->location()); if (!target) return false; - } - TouchEvent translated_event(*event, this, target); - status = ProcessTouchEvent(target, &translated_event); - handled = status != ui::TOUCH_STATUS_UNKNOWN; + TouchEvent translated_event(*event, this, target); + status = ProcessTouchEvent(target, &translated_event); + handled = status != ui::TOUCH_STATUS_UNKNOWN; - if (status == ui::TOUCH_STATUS_QUEUED || - status == ui::TOUCH_STATUS_QUEUED_END) - gesture_recognizer_->QueueTouchEventForGesture(target, *event); + if (status == ui::TOUCH_STATUS_QUEUED || + status == ui::TOUCH_STATUS_QUEUED_END) + gesture_recognizer_->QueueTouchEventForGesture(target, *event); + } + consumer = target; } // Get the list of GestureEvents from GestureRecognizer. scoped_ptr<ui::GestureRecognizer::Gestures> gestures; gestures.reset(gesture_recognizer_->ProcessTouchEventForGesture( - *event, status, target)); + *event, status, consumer)); + if (ProcessGestures(gestures.get())) + handled = true; - return ProcessGestures(gestures.get()) ? true : handled; + return handled; } bool RootWindow::DispatchGestureEvent(GestureEvent* event) { DispatchHeldMouseMove(); - Window* target = capture_window_; + Window* target = NULL; + if (HasCapture(capture_window_, ui::CW_LOCK_TOUCH)) + target = capture_window_; if (!target) { - target = ConsumerToWindow( - gesture_recognizer_->GetTargetForGestureEvent(event)); - if (!target) + GestureConsumer* consumer = + gesture_recognizer_->GetTargetForGestureEvent(event); + if (consumer->ignores_events()) return false; + target = static_cast<Window*>(consumer); } if (target) { @@ -458,21 +467,23 @@ void RootWindow::ConvertPointToNativeScreen(gfx::Point* point) const { point->Offset(location.x(), location.y()); } -void RootWindow::SetCapture(Window* window) { - if (capture_window_ == window) +void RootWindow::SetCapture(Window* window, unsigned int flags) { + if (capture_window_ == window && flags == capture_window_flags_) return; - gesture_recognizer_->CancelNonCapturedTouches(window); + if (flags & ui::CW_LOCK_TOUCH) + gesture_recognizer_->CancelNonCapturedTouches(window); aura::Window* old_capture_window = capture_window_; capture_window_ = window; + capture_window_flags_ = flags; HandleMouseCaptureChanged(old_capture_window); - if (capture_window_) { - // Make all subsequent mouse events and touch go to the capture window. We - // shouldn't need to send an event here as OnCaptureLost should take care of - // that. + if (capture_window_ && flags & ui::CW_LOCK_MOUSE) { + // Make all subsequent mouse events go to the capture window. We + // shouldn't need to send an event here as OnCaptureLost should + // take care of that. if (mouse_moved_handler_ || mouse_button_flags_ != 0) mouse_moved_handler_ = capture_window_; } else { @@ -485,7 +496,12 @@ void RootWindow::SetCapture(Window* window) { void RootWindow::ReleaseCapture(Window* window) { if (capture_window_ != window) return; - SetCapture(NULL); + SetCapture(NULL, 0); +} + +bool RootWindow::HasCapture(Window* window, unsigned int flags) { + return capture_window_ && window == capture_window_ && + ((flags & capture_window_flags_) == flags); } void RootWindow::AdvanceQueuedTouchEvent(Window* window, bool processed) { @@ -589,7 +605,7 @@ void RootWindow::OnCompositingEnded(ui::Compositor*) { // RootWindow, private: void RootWindow::HandleMouseCaptureChanged(Window* old_capture_window) { - if (capture_window_) + if (capture_window_ && capture_window_flags_ & ui::CW_LOCK_MOUSE) host_->SetCapture(); else host_->ReleaseCapture(); @@ -715,17 +731,16 @@ ui::GestureStatus RootWindow::ProcessGestureEvent(Window* target, if (status == ui::GESTURE_STATUS_UNKNOWN) { // The gesture was unprocessed. Generate corresponding mouse events here // (e.g. tap to click). + // TODO(tdresser|sadrul): We may need to stop firing mouse events + // if a mouse lock exists and target != capture_window_. const ui::EventType* types = NULL; - bool generate_move = false; switch (event->type()) { case ui::ET_GESTURE_TAP: case ui::ET_GESTURE_DOUBLE_TAP: // Double click is special cased below. - generate_move = true; types = kTapTypes; break; case ui::ET_GESTURE_SCROLL_BEGIN: - generate_move = true; types = kScrollBeginTypes; break; @@ -741,15 +756,9 @@ ui::GestureStatus RootWindow::ProcessGestureEvent(Window* target, break; } if (types) { - gfx::Point point_in_root(event->location()); - Window::ConvertPointToWindow(target, this, &point_in_root); - // Move the mouse to the new location. - if (generate_move && point_in_root != last_mouse_location_) { - MouseEvent synth(ui::ET_MOUSE_MOVED, point_in_root, - event->root_location(), event->flags()); - if (DispatchMouseEventToTarget(&synth, target)) - status = ui::GESTURE_STATUS_SYNTH_MOUSE; - } + // TODO: remove this. Once we use DispatchMouseEventImpl this shouldn't + // be necessary. + last_mouse_location_ = event->location(); for (const ui::EventType* type = types; *type != ui::ET_UNKNOWN; ++type) { int flags = event->flags(); @@ -761,10 +770,11 @@ ui::GestureStatus RootWindow::ProcessGestureEvent(Window* target, // XI < 2.2, this is always set anyway. flags |= ui::EF_LEFT_MOUSE_BUTTON; - // DispatchMouseEventToTarget() expects coordinates in root, it'll - // convert back to |target|. - MouseEvent synth(*type, point_in_root, event->root_location(), flags); - if (DispatchMouseEventToTarget(&synth, target)) + MouseEvent synth( + *type, event->location(), event->root_location(), flags); + // TODO: this is all wrong. We should be going through + // DispatchMouseEventImpl. + if (ProcessMouseEvent(target, &synth)) status = ui::GESTURE_STATUS_SYNTH_MOUSE; } } @@ -928,6 +938,10 @@ bool RootWindow::IsFocusedWindow(const Window* window) const { } bool RootWindow::DispatchMouseEventImpl(MouseEvent* event) { + static const int kMouseButtonFlagMask = + ui::EF_LEFT_MOUSE_BUTTON | + ui::EF_MIDDLE_MOUSE_BUTTON | + ui::EF_RIGHT_MOUSE_BUTTON; if (ui::IsDIPEnabled()) { float scale = ui::GetDeviceScaleFactor(layer()); ui::Transform transform = layer()->transform(); @@ -936,21 +950,15 @@ bool RootWindow::DispatchMouseEventImpl(MouseEvent* event) { } else { event->UpdateForRootTransform(layer()->transform()); } - Window* target = - mouse_pressed_handler_ ? mouse_pressed_handler_ : capture_window_; - if (!target) - target = GetEventHandlerForPoint(event->location()); - return DispatchMouseEventToTarget(event, target); -} -bool RootWindow::DispatchMouseEventToTarget(MouseEvent* event, - Window* target) { - static const int kMouseButtonFlagMask = - ui::EF_LEFT_MOUSE_BUTTON | - ui::EF_MIDDLE_MOUSE_BUTTON | - ui::EF_RIGHT_MOUSE_BUTTON; last_mouse_location_ = event->location(); synthesize_mouse_move_ = false; + + Window* target = mouse_pressed_handler_; + if (!target && HasCapture(capture_window_, ui::CW_LOCK_MOUSE)) + target = capture_window_; + if (!target) + target = GetEventHandlerForPoint(event->location()); switch (event->type()) { case ui::ET_MOUSE_MOVED: HandleMouseMoved(*event, target); diff --git a/ui/aura/root_window.h b/ui/aura/root_window.h index 53ffab5..708fa6c 100644 --- a/ui/aura/root_window.h +++ b/ui/aura/root_window.h @@ -194,12 +194,19 @@ class AURA_EXPORT RootWindow : public ui::CompositorDelegate, // Capture ------------------------------------------------------------------- - // Sets capture to the specified window. - void SetCapture(Window* window); + // Sets the capture window to |window|, for events specified in + // |flags|. |flags| is ui::CaptureEventFlags. This does nothing if + // the window isn't showing (VISIBILITY_SHOWN), or isn't contained + // in a valid window hierarchy. + void SetCapture(Window* window, unsigned int flags); - // If |window| has capture, the current capture window is set to NULL. + // Stop capturing all events (mouse and touch). void ReleaseCapture(Window* window); + // Returns true if there is a window capturing all event types + // specified by |flags|. |flags| is ui::CaptureEventFlags. + bool HasCapture(Window* window, unsigned int flags); + // Gesture Recognition ------------------------------------------------------- // When a touch event is dispatched to a Window, it can notify the RootWindow @@ -320,10 +327,7 @@ class AURA_EXPORT RootWindow : public ui::CompositorDelegate, // HoldMouseMoves() is called. The following methods are used to dispatch held // and newly incoming mouse events, typically when an event other than a mouse // drag needs dispatching or a matching ReleaseMouseMoves() is called. - // NOTE: because these methods dispatch events from RootWindowHost the - // coordinates are in terms of the root. bool DispatchMouseEventImpl(MouseEvent* event); - bool DispatchMouseEventToTarget(MouseEvent* event, Window* target); void DispatchHeldMouseMove(); // Parses the switch describing the initial size for the host window and @@ -381,6 +385,8 @@ class AURA_EXPORT RootWindow : public ui::CompositorDelegate, // The gesture_recognizer_ for this. scoped_ptr<ui::GestureRecognizer> gesture_recognizer_; + unsigned int capture_window_flags_; + bool synthesize_mouse_move_; bool waiting_on_compositing_end_; bool draw_on_compositing_end_; diff --git a/ui/aura/root_window_host_linux.cc b/ui/aura/root_window_host_linux.cc index 4f42775..d9b9cd3 100644 --- a/ui/aura/root_window_host_linux.cc +++ b/ui/aura/root_window_host_linux.cc @@ -484,7 +484,7 @@ bool RootWindowHostLinux::Dispatch(const base::NativeEvent& event) { } case FocusOut: if (xev->xfocus.mode != NotifyGrab) - root_window_->SetCapture(NULL); + root_window_->SetCapture(NULL, 0); break; case ConfigureNotify: { DCHECK_EQ(xwindow_, xev->xconfigure.window); diff --git a/ui/aura/root_window_host_win.cc b/ui/aura/root_window_host_win.cc index 79060c0..cf746ac 100644 --- a/ui/aura/root_window_host_win.cc +++ b/ui/aura/root_window_host_win.cc @@ -318,7 +318,7 @@ LRESULT RootWindowHostWin::OnCaptureChanged(UINT message, LPARAM l_param) { if (has_capture_) { has_capture_ = false; - root_window_->SetCapture(NULL); + root_window_->SetCapture(NULL, 0); } return 0; } diff --git a/ui/aura/root_window_unittest.cc b/ui/aura/root_window_unittest.cc index 2a53fa6..acc1ea2 100644 --- a/ui/aura/root_window_unittest.cc +++ b/ui/aura/root_window_unittest.cc @@ -451,9 +451,15 @@ TEST_F(RootWindowTest, GestureToMouseEventTest) { root_window()->SetEventFilter(filter); // passes ownership test::TestWindowDelegate delegate; + const int kWindowWidth = 123; + const int kWindowHeight = 45; + gfx::Rect bounds1(100, 200, kWindowWidth, kWindowHeight); + gfx::Rect bounds2(300, 400, kWindowWidth, kWindowHeight); scoped_ptr<aura::Window> window1(CreateTestWindowWithDelegate( &delegate, 1, gfx::Rect(0, 0, 250, 250), NULL)); + gfx::Point location(100, 101); + // ET_TOUCH_PRESSED/RELEASED should generate mouse pressed/released. { TouchEvent touch_pressed_event(ui::ET_TOUCH_PRESSED, gfx::Point(100, 101), @@ -467,7 +473,7 @@ TEST_F(RootWindowTest, GestureToMouseEventTest) { root_window()->DispatchTouchEvent(&touch_pressed_event); root_window()->DispatchTouchEvent(&touch_released_event); EXPECT_EQ("TOUCH_PRESSED GESTURE_TAP_DOWN TOUCH_RELEASED GESTURE_TAP " - "MOUSE_ENTERED MOUSE_MOVED MOUSE_PRESSED MOUSE_RELEASED", + "MOUSE_ENTERED MOUSE_PRESSED MOUSE_RELEASED MOUSE_EXITED", EventTypesToString(filter->events())); filter->events().clear(); } @@ -488,8 +494,8 @@ TEST_F(RootWindowTest, GestureToMouseEventTest) { TouchEvent touch_event(ui::ET_TOUCH_MOVED, gfx::Point(200, 201), 1, base::TimeDelta()); root_window()->DispatchTouchEvent(&touch_event); - EXPECT_EQ("TOUCH_MOVED GESTURE_SCROLL_BEGIN MOUSE_PRESSED MOUSE_DRAGGED " - "GESTURE_SCROLL_UPDATE MOUSE_DRAGGED", + EXPECT_EQ("TOUCH_MOVED GESTURE_SCROLL_BEGIN MOUSE_ENTERED " + "MOUSE_PRESSED MOUSE_DRAGGED GESTURE_SCROLL_UPDATE MOUSE_DRAGGED", EventTypesToString(filter->events())); filter->events().clear(); } @@ -512,47 +518,8 @@ TEST_F(RootWindowTest, GestureToMouseEventTest) { TouchEvent touch_event(ui::ET_TOUCH_RELEASED, gfx::Point(300, 201), 1, base::TimeDelta()); root_window()->DispatchTouchEvent(&touch_event); - EXPECT_EQ("TOUCH_RELEASED GESTURE_SCROLL_END MOUSE_DRAGGED MOUSE_RELEASED", - EventTypesToString(filter->events())); - filter->events().clear(); - } -} - -TEST_F(RootWindowTest, MouseMoveThenTouch) { - EventFilterRecorder* filter = new EventFilterRecorder; - root_window()->SetEventFilter(filter); // passes ownership - - test::TestWindowDelegate delegate; - scoped_ptr<aura::Window> window1(CreateTestWindowWithDelegate( - &delegate, 1, gfx::Rect(0, 0, 100, 100), NULL)); - scoped_ptr<aura::Window> window2(CreateTestWindowWithDelegate( - &delegate, 1, gfx::Rect(150, 150, 50, 50), NULL)); - - // Move the mouse over window1. - { - MouseEvent move_mouse_event(ui::ET_MOUSE_MOVED, gfx::Point(50, 50), - gfx::Point(50, 50), 0); - root_window()->DispatchMouseEvent(&move_mouse_event); - EXPECT_EQ("MOUSE_ENTERED MOUSE_MOVED", - EventTypesToString(filter->events())); - filter->events().clear(); - } - - // Touch window2. - { - TouchEvent touch_pressed_event(ui::ET_TOUCH_PRESSED, gfx::Point(151, 151), - 1, base::TimeDelta()); - int time_ms = - static_cast<int>(ui::GestureConfiguration:: - min_touch_down_duration_in_seconds_for_click() * 1000); - TouchEvent touch_released_event( - ui::ET_TOUCH_RELEASED, gfx::Point(151, 151), 1, - base::TimeDelta::FromMilliseconds(time_ms)); - root_window()->DispatchTouchEvent(&touch_pressed_event); - root_window()->DispatchTouchEvent(&touch_released_event); - EXPECT_EQ("TOUCH_PRESSED GESTURE_TAP_DOWN TOUCH_RELEASED GESTURE_TAP " - "MOUSE_EXITED MOUSE_ENTERED MOUSE_MOVED MOUSE_PRESSED " - "MOUSE_RELEASED", + EXPECT_EQ("TOUCH_RELEASED GESTURE_SCROLL_END MOUSE_DRAGGED MOUSE_RELEASED " + "MOUSE_EXITED", EventTypesToString(filter->events())); filter->events().clear(); } diff --git a/ui/aura/window.cc b/ui/aura/window.cc index 48dbfa9..c059ee5 100644 --- a/ui/aura/window.cc +++ b/ui/aura/window.cc @@ -485,7 +485,7 @@ const internal::FocusManager* Window::GetFocusManager() const { return parent_ ? parent_->GetFocusManager() : NULL; } -void Window::SetCapture() { +void Window::SetCapture(unsigned int flags) { if (!IsVisible()) return; @@ -493,7 +493,7 @@ void Window::SetCapture() { if (!root_window) return; - root_window->SetCapture(this); + root_window->SetCapture(this, flags); } void Window::ReleaseCapture() { @@ -504,9 +504,11 @@ void Window::ReleaseCapture() { root_window->ReleaseCapture(this); } -bool Window::HasCapture() { +bool Window::HasCapture(unsigned int flags) { RootWindow* root_window = GetRootWindow(); - return root_window && root_window->capture_window() == this; + if (!root_window) + return false; + return root_window->HasCapture(this, flags); } void Window::SuppressPaint() { diff --git a/ui/aura/window.h b/ui/aura/window.h index 7917fba..796142c 100644 --- a/ui/aura/window.h +++ b/ui/aura/window.h @@ -296,15 +296,18 @@ class AURA_EXPORT Window : public ui::LayerDelegate, virtual internal::FocusManager* GetFocusManager(); virtual const internal::FocusManager* GetFocusManager() const; - // Does a capture on the window. This does nothing if the window isn't showing - // (VISIBILITY_SHOWN) or isn't contained in a valid window hierarchy. - void SetCapture(); + // Sets the capture window to |window|, for events specified in + // |flags|. |flags| is ui::CaptureEventFlags. This does nothing if + // the window isn't showing (VISIBILITY_SHOWN), or isn't contained + // in a valid window hierarchy. + void SetCapture(unsigned int flags); - // Releases a capture. + // Stop capturing all events (mouse and touch). void ReleaseCapture(); - // Returns true if this window has capture. - bool HasCapture(); + // Returns true if there is a window capturing all event types + // specified by |flags|. |flags| is ui::CaptureEventFlags. + bool HasCapture(unsigned int flags); // Suppresses painting window content by disgarding damaged rect and ignoring // new paint requests. diff --git a/ui/aura/window_unittest.cc b/ui/aura/window_unittest.cc index 1cfac96..4872373 100644 --- a/ui/aura/window_unittest.cc +++ b/ui/aura/window_unittest.cc @@ -540,18 +540,58 @@ TEST_F(WindowTest, StackChildAbove) { EXPECT_EQ(child3.layer(), parent.layer()->children()[2]); } +// Ensure capture of touch events works. +TEST_F(WindowTest, TouchCaptureTests) { +CaptureWindowDelegateImpl delegate; + scoped_ptr<Window> window(CreateTestWindowWithDelegate( + &delegate, 0, gfx::Rect(0, 0, 20, 20), NULL)); + EXPECT_FALSE(window->HasCapture(ui::CW_LOCK_MOUSE)); + EXPECT_FALSE(window->HasCapture(ui::CW_LOCK_TOUCH)); + + delegate.ResetCounts(); + + // Capture touch events. + window->SetCapture(ui::CW_LOCK_TOUCH); + EXPECT_FALSE(window->HasCapture(ui::CW_LOCK_MOUSE)); + EXPECT_TRUE(window->HasCapture(ui::CW_LOCK_TOUCH)); + EXPECT_EQ(0, delegate.capture_lost_count()); + EXPECT_EQ(0, delegate.capture_changed_event_count()); + EventGenerator generator(root_window(), gfx::Point(50, 50)); + generator.PressLeftButton(); + EXPECT_EQ(0, delegate.mouse_event_count()); + + TouchEvent touchev(ui::ET_TOUCH_PRESSED, gfx::Point(50, 50), 0, getTime()); + root_window()->DispatchTouchEvent(&touchev); + EXPECT_EQ(1, delegate.touch_event_count()); + delegate.ResetCounts(); + window->ReleaseCapture(); + + // Capture both touch and mouse events. + window->SetCapture(ui::CW_LOCK_TOUCH | ui::CW_LOCK_MOUSE); + EXPECT_TRUE(window->HasCapture(ui::CW_LOCK_MOUSE)); + EXPECT_TRUE(window->HasCapture(ui::CW_LOCK_TOUCH)); + generator.PressLeftButton(); + EXPECT_EQ(1, delegate.mouse_event_count()); + + TouchEvent touchev2(ui::ET_TOUCH_PRESSED, gfx::Point(50, 50), 1, getTime()); + root_window()->DispatchTouchEvent(&touchev2); + EXPECT_EQ(1, delegate.touch_event_count()); +} + // Various capture assertions. TEST_F(WindowTest, CaptureTests) { CaptureWindowDelegateImpl delegate; scoped_ptr<Window> window(CreateTestWindowWithDelegate( &delegate, 0, gfx::Rect(0, 0, 20, 20), NULL)); - EXPECT_FALSE(window->HasCapture()); + EXPECT_FALSE(window->HasCapture(ui::CW_LOCK_MOUSE)); + EXPECT_FALSE(window->HasCapture(ui::CW_LOCK_TOUCH)); delegate.ResetCounts(); // Do a capture. - window->SetCapture(); - EXPECT_TRUE(window->HasCapture()); + window->SetCapture(ui::CW_LOCK_MOUSE); + EXPECT_TRUE(window->HasCapture(ui::CW_LOCK_MOUSE)); + EXPECT_FALSE(window->HasCapture(ui::CW_LOCK_TOUCH)); EXPECT_EQ(0, delegate.capture_lost_count()); EXPECT_EQ(0, delegate.capture_changed_event_count()); EventGenerator generator(root_window(), gfx::Point(50, 50)); @@ -564,29 +604,29 @@ TEST_F(WindowTest, CaptureTests) { TouchEvent touchev(ui::ET_TOUCH_PRESSED, gfx::Point(50, 50), 0, getTime()); root_window()->DispatchTouchEvent(&touchev); - EXPECT_EQ(1, delegate.touch_event_count()); + EXPECT_EQ(0, delegate.touch_event_count()); delegate.ResetCounts(); window->ReleaseCapture(); - EXPECT_FALSE(window->HasCapture()); + EXPECT_FALSE(window->HasCapture(ui::CW_LOCK_MOUSE)); + EXPECT_FALSE(window->HasCapture(ui::CW_LOCK_TOUCH)); EXPECT_EQ(1, delegate.capture_lost_count()); EXPECT_EQ(1, delegate.capture_changed_event_count()); EXPECT_EQ(1, delegate.mouse_event_count()); - EXPECT_EQ(1, delegate.touch_event_count()); generator.PressLeftButton(); EXPECT_EQ(1, delegate.mouse_event_count()); TouchEvent touchev2(ui::ET_TOUCH_PRESSED, gfx::Point(250, 250), 1, getTime()); root_window()->DispatchTouchEvent(&touchev2); - EXPECT_EQ(1, delegate.touch_event_count()); + EXPECT_EQ(0, delegate.touch_event_count()); // Removing the capture window from parent should reset the capture window // in the root window. - window->SetCapture(); + window->SetCapture(ui::CW_LOCK_MOUSE); EXPECT_EQ(window.get(), root_window()->capture_window()); window->parent()->RemoveChild(window.get()); - EXPECT_FALSE(window->HasCapture()); + EXPECT_FALSE(window->HasCapture(ui::CW_LOCK_MOUSE)); EXPECT_EQ(NULL, root_window()->capture_window()); } @@ -604,7 +644,7 @@ TEST_F(WindowTest, TouchCaptureCancelsOtherTouches) { root_window()->DispatchTouchEvent(&press); EXPECT_EQ(1, delegate1.gesture_event_count()); delegate1.ResetCounts(); - w2->SetCapture(); + w2->SetCapture(ui::CW_LOCK_TOUCH); // The touch was cancelled when the other window // attained a touch lock. @@ -649,7 +689,7 @@ TEST_F(WindowTest, TouchCaptureDoesntCancelCapturedTouches) { EXPECT_EQ(1, delegate.gesture_event_count()); delegate.ResetCounts(); - window->SetCapture(); + window->SetCapture(ui::CW_LOCK_TOUCH); EXPECT_EQ(0, delegate.gesture_event_count()); delegate.ResetCounts(); @@ -675,12 +715,13 @@ TEST_F(WindowTest, ChangeCaptureWhileMouseDown) { // aggregated. RunAllPendingInMessageLoop(); - EXPECT_FALSE(window->HasCapture()); + EXPECT_FALSE(window->HasCapture(ui::CW_LOCK_MOUSE)); + EXPECT_FALSE(window->HasCapture(ui::CW_LOCK_TOUCH)); // Do a capture. delegate.ResetCounts(); - window->SetCapture(); - EXPECT_TRUE(window->HasCapture()); + window->SetCapture(ui::CW_LOCK_MOUSE); + EXPECT_TRUE(window->HasCapture(ui::CW_LOCK_MOUSE)); EXPECT_EQ(0, delegate.capture_lost_count()); EXPECT_EQ(0, delegate.capture_changed_event_count()); EventGenerator generator(root_window(), gfx::Point(50, 50)); @@ -692,7 +733,7 @@ TEST_F(WindowTest, ChangeCaptureWhileMouseDown) { // Set capture to |w2|, should implicitly unset capture for |window|. delegate.ResetCounts(); delegate2.ResetCounts(); - w2->SetCapture(); + w2->SetCapture(ui::CW_LOCK_MOUSE); generator.MoveMouseTo(gfx::Point(40, 40), 2); EXPECT_EQ(1, delegate.capture_lost_count()); @@ -706,11 +747,11 @@ TEST_F(WindowTest, ReleaseCaptureOnDestroy) { CaptureWindowDelegateImpl delegate; scoped_ptr<Window> window(CreateTestWindowWithDelegate( &delegate, 0, gfx::Rect(0, 0, 20, 20), NULL)); - EXPECT_FALSE(window->HasCapture()); + EXPECT_FALSE(window->HasCapture(ui::CW_LOCK_MOUSE)); // Do a capture. - window->SetCapture(); - EXPECT_TRUE(window->HasCapture()); + window->SetCapture(ui::CW_LOCK_MOUSE); + EXPECT_TRUE(window->HasCapture(ui::CW_LOCK_MOUSE)); // Destroy the window. window.reset(); diff --git a/ui/base/events.h b/ui/base/events.h index e0e712d..1bf5ec4 100644 --- a/ui/base/events.h +++ b/ui/base/events.h @@ -105,6 +105,11 @@ enum TouchStatus { // handler. }; +enum CaptureEventFlags { + CW_LOCK_MOUSE = 1 << 0, + CW_LOCK_TOUCH = 1 << 1, +}; + // Updates the list of devices for cached properties. UI_EXPORT void UpdateDeviceList(); diff --git a/ui/base/gestures/gesture_recognizer_impl.cc b/ui/base/gestures/gesture_recognizer_impl.cc index bd29c46..ead6aa0 100644 --- a/ui/base/gestures/gesture_recognizer_impl.cc +++ b/ui/base/gestures/gesture_recognizer_impl.cc @@ -95,7 +95,7 @@ GestureRecognizerImpl::~GestureRecognizerImpl() { } GestureConsumer* GestureRecognizerImpl::GetTouchLockedTarget( - TouchEvent* event) { + TouchEvent* event) { return touch_id_target_[event->GetTouchId()]; } @@ -120,7 +120,7 @@ GestureConsumer* GestureRecognizerImpl::GetTargetForLocation( gfx::Point delta = points[j].last_touch_position().Subtract(location); int distance = delta.x() * delta.x() + delta.y() * delta.y(); - if (!closest_point || distance < closest_distance_squared) { + if ( !closest_point || distance < closest_distance_squared ) { closest_point = &points[j]; closest_distance_squared = distance; } diff --git a/ui/base/gestures/gesture_types.h b/ui/base/gestures/gesture_types.h index 7ed5a86..b857171 100644 --- a/ui/base/gestures/gesture_types.h +++ b/ui/base/gestures/gesture_types.h @@ -51,9 +51,6 @@ class UI_EXPORT GestureConsumer { } virtual ~GestureConsumer() {} - - // TODO: this is a hack! GestureRecognizer should never expose the internal - // marker object that implements this. bool ignores_events() { return ignores_events_; } private: diff --git a/ui/views/controls/menu/menu_host.cc b/ui/views/controls/menu/menu_host.cc index a9f2f7f..4a887e5 100644 --- a/ui/views/controls/menu/menu_host.cc +++ b/ui/views/controls/menu/menu_host.cc @@ -49,7 +49,7 @@ void MenuHost::ShowMenuHost(bool do_capture) { ignore_capture_lost_ = true; Show(); if (do_capture) - native_widget_private()->SetCapture(); + native_widget_private()->SetCapture(ui::CW_LOCK_MOUSE | ui::CW_LOCK_TOUCH); ignore_capture_lost_ = false; } @@ -72,7 +72,8 @@ void MenuHost::SetMenuHostBounds(const gfx::Rect& bounds) { } void MenuHost::ReleaseMenuHostCapture() { - if (native_widget_private()->HasCapture()) + if (native_widget_private()->HasCapture(ui::CW_LOCK_MOUSE) || + native_widget_private()->HasCapture(ui::CW_LOCK_TOUCH)) native_widget_private()->ReleaseCapture(); } diff --git a/ui/views/widget/native_widget_aura.cc b/ui/views/widget/native_widget_aura.cc index b63e8fd..d840fa1 100644 --- a/ui/views/widget/native_widget_aura.cc +++ b/ui/views/widget/native_widget_aura.cc @@ -325,16 +325,16 @@ void NativeWidgetAura::SendNativeAccessibilityEvent( //NOTIMPLEMENTED(); } -void NativeWidgetAura::SetCapture() { - window_->SetCapture(); +void NativeWidgetAura::SetCapture(unsigned int flags) { + window_->SetCapture(flags); } void NativeWidgetAura::ReleaseCapture() { window_->ReleaseCapture(); } -bool NativeWidgetAura::HasCapture() const { - return window_->HasCapture(); +bool NativeWidgetAura::HasCapture(unsigned int flags) const { + return window_->HasCapture(flags); } InputMethod* NativeWidgetAura::CreateInputMethod() { @@ -653,7 +653,7 @@ void NativeWidgetAura::SetInactiveRenderingDisabled(bool value) { Widget::MoveLoopResult NativeWidgetAura::RunMoveLoop() { if (window_->parent() && aura::client::GetWindowMoveClient(window_->parent())) { - SetCapture(); + SetCapture(ui::CW_LOCK_MOUSE); aura::client::GetWindowMoveClient(window_->parent())->RunMoveLoop(window_); return Widget::MOVE_LOOP_SUCCESSFUL; } diff --git a/ui/views/widget/native_widget_aura.h b/ui/views/widget/native_widget_aura.h index c9a1480..7a66d2e 100644 --- a/ui/views/widget/native_widget_aura.h +++ b/ui/views/widget/native_widget_aura.h @@ -65,9 +65,9 @@ class VIEWS_EXPORT NativeWidgetAura : public internal::NativeWidgetPrivate, virtual void SendNativeAccessibilityEvent( View* view, ui::AccessibilityTypes::Event event_type) OVERRIDE; - virtual void SetCapture() OVERRIDE; + virtual void SetCapture(unsigned int flags) OVERRIDE; virtual void ReleaseCapture() OVERRIDE; - virtual bool HasCapture() const OVERRIDE; + virtual bool HasCapture(unsigned int flags) const OVERRIDE; virtual InputMethod* CreateInputMethod() OVERRIDE; virtual void CenterWindow(const gfx::Size& size) OVERRIDE; virtual void GetWindowPlacement( diff --git a/ui/views/widget/native_widget_private.h b/ui/views/widget/native_widget_private.h index a56e5a6d..19fa904 100644 --- a/ui/views/widget/native_widget_private.h +++ b/ui/views/widget/native_widget_private.h @@ -121,12 +121,18 @@ class VIEWS_EXPORT NativeWidgetPrivate : public NativeWidget, View* view, ui::AccessibilityTypes::Event event_type) = 0; - // Sets or releases event capturing for this native widget. - virtual void SetCapture() = 0; + // Sets event capturing for the native widget for events specified in + // |flags|. |flags| is ui::CaptureEventFlags. This does nothing if + // the window isn't showing (VISIBILITY_SHOWN), or isn't contained + // in a valid window hierarchy. + virtual void SetCapture(unsigned int flags) = 0; + + // Stop capturing events. virtual void ReleaseCapture() = 0; - // Returns true if this native widget is capturing events. - virtual bool HasCapture() const = 0; + // Returns true if this native widget is capturing all event types + // specified by |flags|. flags is ui::CaptureEventFlags. + virtual bool HasCapture(unsigned int flags) const = 0; // Returns the InputMethod for this native widget. // Note that all widgets in a widget hierarchy share the same input method. diff --git a/ui/views/widget/native_widget_win.cc b/ui/views/widget/native_widget_win.cc index 975b905..1cbc98b 100644 --- a/ui/views/widget/native_widget_win.cc +++ b/ui/views/widget/native_widget_win.cc @@ -650,17 +650,21 @@ void NativeWidgetWin::SendNativeAccessibilityEvent( GetNativeView(), OBJID_CLIENT, child_id); } -void NativeWidgetWin::SetCapture() { - DCHECK(!HasCapture()); - ::SetCapture(hwnd()); +void NativeWidgetWin::SetCapture(unsigned int flags) { + if (flags & ui::CW_LOCK_MOUSE) { + DCHECK(!HasCapture(ui::CW_LOCK_MOUSE)); + ::SetCapture(hwnd()); + } } void NativeWidgetWin::ReleaseCapture() { ::ReleaseCapture(); } -bool NativeWidgetWin::HasCapture() const { - return ::GetCapture() == hwnd(); +bool NativeWidgetWin::HasCapture(unsigned int flags) const { + if (flags == ui::CW_LOCK_MOUSE) + return ::GetCapture() == hwnd(); + return false; } InputMethod* NativeWidgetWin::CreateInputMethod() { @@ -1576,7 +1580,7 @@ LRESULT NativeWidgetWin::OnMouseRange(UINT message, // We SetCapture() to ensure we only show the menu when the button // down and up are both on the caption. Note: this causes the button up to // be WM_RBUTTONUP instead of WM_NCRBUTTONUP. - SetCapture(); + SetCapture(ui::CW_LOCK_MOUSE); } MSG msg = { hwnd(), message, w_param, l_param, 0, @@ -1587,7 +1591,7 @@ LRESULT NativeWidgetWin::OnMouseRange(UINT message, if (tooltip_manager_.get()) tooltip_manager_->OnMouse(message, w_param, l_param); - if (event.type() == ui::ET_MOUSE_MOVED && !HasCapture()) { + if (event.type() == ui::ET_MOUSE_MOVED && !HasCapture(ui::CW_LOCK_MOUSE)) { // 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. diff --git a/ui/views/widget/native_widget_win.h b/ui/views/widget/native_widget_win.h index 5e1b7b7..059425c 100644 --- a/ui/views/widget/native_widget_win.h +++ b/ui/views/widget/native_widget_win.h @@ -194,9 +194,10 @@ class VIEWS_EXPORT NativeWidgetWin : public ui::WindowImpl, virtual void SendNativeAccessibilityEvent( View* view, ui::AccessibilityTypes::Event event_type) OVERRIDE; - virtual void SetCapture() OVERRIDE; + // NativeWidgetWin ignores touch captures. + virtual void SetCapture(unsigned int flags) OVERRIDE; virtual void ReleaseCapture() OVERRIDE; - virtual bool HasCapture() const OVERRIDE; + virtual bool HasCapture(unsigned int flags) const OVERRIDE; virtual InputMethod* CreateInputMethod() OVERRIDE; virtual void CenterWindow(const gfx::Size& size) OVERRIDE; virtual void GetWindowPlacement( diff --git a/ui/views/widget/widget.cc b/ui/views/widget/widget.cc index e238c67..2cb0caa 100644 --- a/ui/views/widget/widget.cc +++ b/ui/views/widget/widget.cc @@ -827,12 +827,12 @@ NativeWidget* Widget::native_widget() { void Widget::SetMouseCapture(views::View* view) { is_mouse_button_pressed_ = true; root_view_->SetMouseHandler(view); - if (!native_widget_->HasCapture()) - native_widget_->SetCapture(); + if (!native_widget_->HasCapture(ui::CW_LOCK_MOUSE)) + native_widget_->SetCapture(ui::CW_LOCK_MOUSE); } void Widget::ReleaseMouseCapture() { - if (native_widget_->HasCapture()) + if (native_widget_->HasCapture(ui::CW_LOCK_MOUSE)) native_widget_->ReleaseCapture(); } @@ -1046,8 +1046,8 @@ bool Widget::OnMouseEvent(const MouseEvent& event) { // press processing may have made the window hide (as happens with menus). if (GetRootView()->OnMousePressed(event) && IsVisible()) { is_mouse_button_pressed_ = true; - if (!native_widget_->HasCapture()) - native_widget_->SetCapture(); + if (!native_widget_->HasCapture(ui::CW_LOCK_MOUSE)) + native_widget_->SetCapture(ui::CW_LOCK_MOUSE); return true; } return false; @@ -1055,7 +1055,7 @@ bool Widget::OnMouseEvent(const MouseEvent& event) { last_mouse_event_was_move_ = false; is_mouse_button_pressed_ = false; // Release capture first, to avoid confusion if OnMouseReleased blocks. - if (native_widget_->HasCapture() && + if (native_widget_->HasCapture(ui::CW_LOCK_MOUSE) && ShouldReleaseCaptureOnMouseReleased()) { native_widget_->ReleaseCapture(); } @@ -1063,7 +1063,8 @@ bool Widget::OnMouseEvent(const MouseEvent& event) { return (event.flags() & ui::EF_IS_NON_CLIENT) ? false : true; case ui::ET_MOUSE_MOVED: case ui::ET_MOUSE_DRAGGED: - if (native_widget_->HasCapture() && is_mouse_button_pressed_) { + if (native_widget_->HasCapture(ui::CW_LOCK_MOUSE) && + is_mouse_button_pressed_) { last_mouse_event_was_move_ = false; GetRootView()->OnMouseDragged(event); } else if (!last_mouse_event_was_move_ || diff --git a/ui/views/widget/widget_unittest.cc b/ui/views/widget/widget_unittest.cc index 9716a6c..df2c1b7 100644 --- a/ui/views/widget/widget_unittest.cc +++ b/ui/views/widget/widget_unittest.cc @@ -41,7 +41,9 @@ class NativeWidgetCapture : public NativeWidgetPlatform { mouse_capture_(false) {} virtual ~NativeWidgetCapture() {} - virtual void SetCapture() OVERRIDE { + virtual void SetCapture(unsigned int flags) OVERRIDE { + if (!(flags & ui::CW_LOCK_MOUSE)) + return; mouse_capture_ = true; } virtual void ReleaseCapture() OVERRIDE { @@ -49,8 +51,10 @@ class NativeWidgetCapture : public NativeWidgetPlatform { delegate()->OnMouseCaptureLost(); mouse_capture_ = false; } - virtual bool HasCapture() const OVERRIDE { - return mouse_capture_; + virtual bool HasCapture(unsigned int flags) const OVERRIDE { + if (flags == ui::CW_LOCK_MOUSE) + return mouse_capture_; + return false; } private: @@ -142,7 +146,7 @@ Widget* CreateChildNativeWidget() { bool WidgetHasMouseCapture(const Widget* widget) { return static_cast<const internal::NativeWidgetPrivate*>(widget-> - native_widget())->HasCapture(); + native_widget())->HasCapture(ui::CW_LOCK_MOUSE); } ui::WindowShowState GetWidgetShowState(const Widget* widget) { |