From 759017e03abb02554ad06a1745290631c43d7751 Mon Sep 17 00:00:00 2001 From: "pkotwicz@chromium.org" Date: Sat, 11 Feb 2012 20:46:11 +0000 Subject: 1) Invoke RootWindow::SetCapture(NULL) as a result from OS level mouse capture lost (eg from a popup) 2) Invoke OS level SetCapture, ReleaseCapture as a result of setting capture on root window BUG=107875 TEST= 1) Make sure that bug 105993 does not repro Review URL: https://chromiumcodereview.appspot.com/9228004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@121655 0039d316-1c4b-4281-b951-d872f2087c98 --- ui/aura/root_window.cc | 25 +++++++++++++++++--- ui/aura/root_window.h | 4 ++++ ui/aura/root_window_host.h | 6 +++++ ui/aura/root_window_host_linux.cc | 14 ++++++++++- ui/aura/root_window_host_win.cc | 25 ++++++++++++++++++++ ui/aura/root_window_host_win.h | 7 ++++++ ui/aura/window_unittest.cc | 50 ++++++++++++++++++++++++++------------- ui/base/events.h | 1 + 8 files changed, 112 insertions(+), 20 deletions(-) (limited to 'ui') diff --git a/ui/aura/root_window.cc b/ui/aura/root_window.cc index 742d265..193a50d 100644 --- a/ui/aura/root_window.cc +++ b/ui/aura/root_window.cc @@ -296,8 +296,10 @@ void RootWindow::OnWindowDestroying(Window* window) { mouse_pressed_handler_ = NULL; if (mouse_moved_handler_ == window) mouse_moved_handler_ = NULL; - if (capture_window_ == window) + if (capture_window_ == window) { capture_window_ = NULL; + host_->ReleaseCapture(); + } if (touch_event_handler_ == window) touch_event_handler_ = NULL; if (gesture_handler_ == window) @@ -366,10 +368,11 @@ void RootWindow::SetCapture(Window* window) { if (capture_window_ == window) return; - if (capture_window_ && capture_window_->delegate()) - capture_window_->delegate()->OnCaptureLost(); + aura::Window* old_capture_window = capture_window_; capture_window_ = window; + 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 @@ -487,6 +490,22 @@ RootWindow::~RootWindow() { instance_ = NULL; } +void RootWindow::HandleMouseCaptureChanged(Window* old_capture_window) { + if (capture_window_) + host_->SetCapture(); + else + host_->ReleaseCapture(); + + if (old_capture_window && old_capture_window->delegate()) { + // Send a capture changed event with bogus location data. + MouseEvent event( + ui::ET_MOUSE_CAPTURE_CHANGED, gfx::Point(), gfx::Point(), 0); + ProcessMouseEvent(old_capture_window, &event); + + old_capture_window->delegate()->OnCaptureLost(); + } +} + void RootWindow::HandleMouseMoved(const MouseEvent& event, Window* target) { if (target == mouse_moved_handler_) return; diff --git a/ui/aura/root_window.h b/ui/aura/root_window.h index 917b0c0..3122b53 100644 --- a/ui/aura/root_window.h +++ b/ui/aura/root_window.h @@ -202,6 +202,10 @@ class AURA_EXPORT RootWindow : public ui::CompositorDelegate, // sending exited and entered events as its value changes. void HandleMouseMoved(const MouseEvent& event, Window* target); + // Called whenever the |capture_window_| changes. + // Sends capture changed events to event filters for old capture window. + void HandleMouseCaptureChanged(Window* old_capture_window); + bool ProcessMouseEvent(Window* target, MouseEvent* event); bool ProcessKeyEvent(Window* target, KeyEvent* event); ui::TouchStatus ProcessTouchEvent(Window* target, TouchEvent* event); diff --git a/ui/aura/root_window_host.h b/ui/aura/root_window_host.h index 476ba6a..551aaf9 100644 --- a/ui/aura/root_window_host.h +++ b/ui/aura/root_window_host.h @@ -58,6 +58,12 @@ class RootWindowHost : public MessageLoop::Dispatcher { // Returns the location of the RootWindow on native screen. virtual gfx::Point GetLocationOnNativeScreen() const = 0; + // Set the OS capture to the root window. + virtual void SetCapture() = 0; + + // Release OS capture of the root window. + virtual void ReleaseCapture() = 0; + // Sets the currently displayed cursor. Shows the cursor by default. // If you want to update hidden cursor, should call ShowCursor(false) // after this function. diff --git a/ui/aura/root_window_host_linux.cc b/ui/aura/root_window_host_linux.cc index 0459ad9..67655fe 100644 --- a/ui/aura/root_window_host_linux.cc +++ b/ui/aura/root_window_host_linux.cc @@ -291,6 +291,8 @@ class RootWindowHostLinux : public RootWindowHost, virtual gfx::Size GetSize() const OVERRIDE; virtual void SetSize(const gfx::Size& size) OVERRIDE; virtual gfx::Point GetLocationOnNativeScreen() const OVERRIDE; + virtual void SetCapture() OVERRIDE; + virtual void ReleaseCapture() OVERRIDE; virtual void SetCursor(gfx::NativeCursor cursor_type) OVERRIDE; virtual void ShowCursor(bool show) OVERRIDE; virtual gfx::Point QueryMouseLocation() OVERRIDE; @@ -353,7 +355,7 @@ RootWindowHostLinux::RootWindowHostLinux(const gfx::Rect& bounds) CWBackPixmap, &swa); - long event_mask = ButtonPressMask | ButtonReleaseMask | + long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask | KeyPressMask | KeyReleaseMask | EnterWindowMask | LeaveWindowMask | ExposureMask | VisibilityChangeMask | @@ -419,6 +421,10 @@ base::MessagePumpDispatcher::DispatchStatus RootWindowHostLinux::Dispatch( handled = root_window_->DispatchMouseEvent(&mouseev); break; } + case FocusOut: + if (xev->xfocus.mode != NotifyGrab) + root_window_->SetCapture(NULL); + break; case ConfigureNotify: { if (xev->xconfigure.window == x_root_window_) { root_window_->OnNativeScreenResized( @@ -590,6 +596,12 @@ gfx::Point RootWindowHostLinux::GetLocationOnNativeScreen() const { return bounds_.origin(); } +void RootWindowHostLinux::SetCapture() { +} + +void RootWindowHostLinux::ReleaseCapture() { +} + void RootWindowHostLinux::SetCursor(gfx::NativeCursor cursor) { if (cursor == kCursorNone && is_cursor_visible_) { current_cursor_ = cursor; diff --git a/ui/aura/root_window_host_win.cc b/ui/aura/root_window_host_win.cc index 705cf9a..a4f60b6 100644 --- a/ui/aura/root_window_host_win.cc +++ b/ui/aura/root_window_host_win.cc @@ -115,6 +115,7 @@ gfx::Size RootWindowHost::GetNativeScreenSize() { RootWindowHostWin::RootWindowHostWin(const gfx::Rect& bounds) : root_window_(NULL), fullscreen_(false), + has_capture_(false), saved_window_style_(0), saved_window_ex_style_(0) { Init(NULL, bounds); @@ -223,6 +224,20 @@ void RootWindowHostWin::SetCursor(gfx::NativeCursor native_cursor) { ::SetCursor(LoadCursor(NULL, cursor_id)); } +void RootWindowHostWin::SetCapture() { + if (!has_capture_) { + has_capture_ = true; + ::SetCapture(hwnd()); + } +} + +void RootWindowHostWin::ReleaseCapture() { + if (has_capture_) { + has_capture_ = false; + ::ReleaseCapture(); + } +} + void RootWindowHostWin::ShowCursor(bool show) { // NOTIMPLEMENTED(); } @@ -284,6 +299,16 @@ LRESULT RootWindowHostWin::OnMouseRange(UINT message, return 0; } +LRESULT RootWindowHostWin::OnCaptureChanged(UINT message, + WPARAM w_param, + LPARAM l_param) { + if (has_capture_) { + has_capture_ = false; + root_window_->SetCapture(NULL); + } + return 0; +} + void RootWindowHostWin::OnPaint(HDC dc) { root_window_->Draw(); ValidateRect(hwnd(), NULL); diff --git a/ui/aura/root_window_host_win.h b/ui/aura/root_window_host_win.h index b3b4443..3e1edcb 100644 --- a/ui/aura/root_window_host_win.h +++ b/ui/aura/root_window_host_win.h @@ -28,6 +28,8 @@ class RootWindowHostWin : public RootWindowHost, public ui::WindowImpl { virtual gfx::Size GetSize() const OVERRIDE; virtual void SetSize(const gfx::Size& size) OVERRIDE; virtual gfx::Point GetLocationOnNativeScreen() const OVERRIDE; + virtual void SetCapture() OVERRIDE; + virtual void ReleaseCapture() OVERRIDE; virtual void SetCursor(gfx::NativeCursor cursor) OVERRIDE; virtual void ShowCursor(bool show) OVERRIDE; virtual gfx::Point QueryMouseLocation() OVERRIDE; @@ -42,6 +44,9 @@ class RootWindowHostWin : public RootWindowHost, public ui::WindowImpl { MESSAGE_RANGE_HANDLER_EX(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseRange) MESSAGE_RANGE_HANDLER_EX(WM_NCMOUSEMOVE, WM_NCXBUTTONDBLCLK, OnMouseRange) + // Mouse capture events. + MESSAGE_HANDLER_EX(WM_CAPTURECHANGED, OnCaptureChanged) + // Key events. MESSAGE_HANDLER_EX(WM_KEYDOWN, OnKeyEvent) MESSAGE_HANDLER_EX(WM_KEYUP, OnKeyEvent) @@ -59,12 +64,14 @@ class RootWindowHostWin : public RootWindowHost, public ui::WindowImpl { void OnClose(); LRESULT OnKeyEvent(UINT message, WPARAM w_param, LPARAM l_param); LRESULT OnMouseRange(UINT message, WPARAM w_param, LPARAM l_param); + LRESULT OnCaptureChanged(UINT message, WPARAM w_param, LPARAM l_param); void OnPaint(HDC dc); void OnSize(UINT param, const CSize& size); RootWindow* root_window_; bool fullscreen_; + bool has_capture_; RECT saved_window_rect_; DWORD saved_window_style_; DWORD saved_window_ex_style_; diff --git a/ui/aura/window_unittest.cc b/ui/aura/window_unittest.cc index 18e85f4..372dc3f 100644 --- a/ui/aura/window_unittest.cc +++ b/ui/aura/window_unittest.cc @@ -116,20 +116,27 @@ class DestroyOrphanDelegate : public TestWindowDelegate { // Used in verifying mouse capture. class CaptureWindowDelegateImpl : public TestWindowDelegate { public: - explicit CaptureWindowDelegateImpl() - : capture_lost_count_(0), - mouse_event_count_(0), - touch_event_count_(0) { + CaptureWindowDelegateImpl() { + ResetCounts(); } + void ResetCounts() { + capture_changed_event_count_ = 0; + capture_lost_count_ = 0; + mouse_event_count_ = 0; + touch_event_count_ = 0; + } + + int capture_changed_event_count() const { + return capture_changed_event_count_; + } int capture_lost_count() const { return capture_lost_count_; } - void set_capture_lost_count(int value) { capture_lost_count_ = value; } int mouse_event_count() const { return mouse_event_count_; } - void set_mouse_event_count(int value) { mouse_event_count_ = value; } int touch_event_count() const { return touch_event_count_; } - void set_touch_event_count(int value) { touch_event_count_ = value; } virtual bool OnMouseEvent(MouseEvent* event) OVERRIDE { + if (event->type() == ui::ET_MOUSE_CAPTURE_CHANGED) + capture_changed_event_count_++; mouse_event_count_++; return false; } @@ -145,6 +152,7 @@ class CaptureWindowDelegateImpl : public TestWindowDelegate { } private: + int capture_changed_event_count_; int capture_lost_count_; int mouse_event_count_; int touch_event_count_; @@ -483,29 +491,34 @@ TEST_F(WindowTest, CaptureTests) { &delegate, 0, gfx::Rect(0, 0, 20, 20), NULL)); EXPECT_FALSE(window->HasCapture()); + delegate.ResetCounts(); + // Do a capture. window->SetCapture(); EXPECT_TRUE(window->HasCapture()); EXPECT_EQ(0, delegate.capture_lost_count()); + EXPECT_EQ(0, delegate.capture_changed_event_count()); EventGenerator generator(gfx::Point(50, 50)); generator.PressLeftButton(); EXPECT_EQ(1, delegate.mouse_event_count()); generator.ReleaseLeftButton(); EXPECT_EQ(2, delegate.mouse_event_count()); - delegate.set_mouse_event_count(0); + delegate.ResetCounts(); TouchEvent touchev(ui::ET_TOUCH_PRESSED, gfx::Point(50, 50), 0); root_window->DispatchTouchEvent(&touchev); EXPECT_EQ(1, delegate.touch_event_count()); - delegate.set_touch_event_count(0); + delegate.ResetCounts(); window->ReleaseCapture(); EXPECT_FALSE(window->HasCapture()); EXPECT_EQ(1, delegate.capture_lost_count()); + EXPECT_EQ(1, delegate.capture_changed_event_count()); + EXPECT_EQ(1, delegate.mouse_event_count()); generator.PressLeftButton(); - EXPECT_EQ(0, delegate.mouse_event_count()); + EXPECT_EQ(1, delegate.mouse_event_count()); root_window->DispatchTouchEvent(&touchev); EXPECT_EQ(0, delegate.touch_event_count()); @@ -530,21 +543,26 @@ TEST_F(WindowTest, ChangeCaptureWhileMouseDown) { EXPECT_FALSE(window->HasCapture()); // Do a capture. + delegate.ResetCounts(); window->SetCapture(); - delegate.set_mouse_event_count(0); EXPECT_TRUE(window->HasCapture()); EXPECT_EQ(0, delegate.capture_lost_count()); + EXPECT_EQ(0, delegate.capture_changed_event_count()); EventGenerator generator(gfx::Point(50, 50)); generator.PressLeftButton(); + EXPECT_EQ(0, delegate.capture_lost_count()); + EXPECT_EQ(0, delegate.capture_changed_event_count()); EXPECT_EQ(1, delegate.mouse_event_count()); - delegate.set_mouse_event_count(0); - // Reset the capture. - window->ReleaseCapture(); + // Set capture to |w2|, should implicitly unset capture for |window|. + delegate.ResetCounts(); + delegate2.ResetCounts(); w2->SetCapture(); - delegate2.set_mouse_event_count(0); + generator.MoveMouseTo(gfx::Point(40, 40), 2); - EXPECT_EQ(0, delegate.mouse_event_count()); + EXPECT_EQ(1, delegate.capture_lost_count()); + EXPECT_EQ(1, delegate.capture_changed_event_count()); + EXPECT_EQ(1, delegate.mouse_event_count()); EXPECT_EQ(2, delegate2.mouse_event_count()); } diff --git a/ui/base/events.h b/ui/base/events.h index 0989e9f..60620f1 100644 --- a/ui/base/events.h +++ b/ui/base/events.h @@ -32,6 +32,7 @@ enum EventType { ET_KEY_PRESSED, ET_KEY_RELEASED, ET_MOUSEWHEEL, + ET_MOUSE_CAPTURE_CHANGED, // Event has no location. ET_TOUCH_RELEASED, ET_TOUCH_PRESSED, ET_TOUCH_MOVED, -- cgit v1.1