summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordbeam@chromium.org <dbeam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-28 09:51:44 +0000
committerdbeam@chromium.org <dbeam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-28 09:51:44 +0000
commit08a0073bb8b13399d112db41ed57c2c2aa87375d (patch)
treef03d1f652ebb7d2857b8093864cde19b5beb2a4e
parentbba8921b1bbfb8da79bd8484df6c5b952363c367 (diff)
downloadchromium_src-08a0073bb8b13399d112db41ed57c2c2aa87375d.zip
chromium_src-08a0073bb8b13399d112db41ed57c2c2aa87375d.tar.gz
chromium_src-08a0073bb8b13399d112db41ed57c2c2aa87375d.tar.bz2
Fix autofill popup stickiness.
Unhandled clicks while the autofill popup is showing should dismiss it. Additionally, forward mouse events that aren't directly useful to the popup. R=estade@chromium.org,sadrul@chromium.org,sky@chromium.org BUG=259529 Review URL: https://chromiumcodereview.appspot.com/19458003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@219974 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--ash/screen_ash.cc7
-rw-r--r--ash/screen_ash.h4
-rw-r--r--chrome/browser/ui/autofill/autofill_dialog_controller_impl.cc8
-rw-r--r--chrome/browser/ui/autofill/autofill_dialog_controller_impl.h1
-rw-r--r--chrome/browser/ui/autofill/autofill_dialog_controller_unittest.cc4
-rw-r--r--chrome/browser/ui/autofill/autofill_dialog_view.h5
-rw-r--r--chrome/browser/ui/autofill/autofill_popup_controller.h10
-rw-r--r--chrome/browser/ui/autofill/autofill_popup_controller_impl.cc15
-rw-r--r--chrome/browser/ui/autofill/autofill_popup_controller_impl.h8
-rw-r--r--chrome/browser/ui/cocoa/autofill/autofill_dialog_cocoa.h2
-rw-r--r--chrome/browser/ui/cocoa/autofill/autofill_dialog_cocoa.mm6
-rw-r--r--chrome/browser/ui/views/autofill/autofill_dialog_views.cc28
-rw-r--r--chrome/browser/ui/views/autofill/autofill_dialog_views.h2
-rw-r--r--chrome/browser/ui/views/autofill/autofill_popup_view_views.cc49
-rw-r--r--chrome/browser/ui/views/panels/panel_view.cc2
-rw-r--r--chrome/browser/ui/window_sizer/window_sizer_common_unittest.cc8
-rw-r--r--components/autofill/core/browser/autofill_external_delegate.cc5
-rw-r--r--components/autofill/core/browser/autofill_external_delegate.h1
-rw-r--r--components/autofill/core/browser/autofill_popup_delegate.h8
-rw-r--r--ui/aura/test/test_screen.cc7
-rw-r--r--ui/aura/test/test_screen.h4
-rw-r--r--ui/gfx/screen.h7
-rw-r--r--ui/gfx/screen_android.cc8
-rw-r--r--ui/gfx/screen_gtk.cc8
-rw-r--r--ui/gfx/screen_ios.mm8
-rw-r--r--ui/gfx/screen_mac.mm8
-rw-r--r--ui/gfx/screen_win.cc12
-rw-r--r--ui/gfx/screen_win.h4
-rw-r--r--ui/views/controls/menu/menu_controller.cc132
-rw-r--r--ui/views/event_utils.h25
-rw-r--r--ui/views/event_utils_aura.cc49
-rw-r--r--ui/views/event_utils_win.cc59
-rw-r--r--ui/views/mouse_watcher_view_host.cc2
-rw-r--r--ui/views/views.gyp3
-rw-r--r--ui/views/widget/desktop_aura/desktop_screen_x11.cc12
-rw-r--r--ui/views/win/hwnd_message_handler.h4
36 files changed, 407 insertions, 118 deletions
diff --git a/ash/screen_ash.cc b/ash/screen_ash.cc
index 4ba2868..31c5bcc 100644
--- a/ash/screen_ash.cc
+++ b/ash/screen_ash.cc
@@ -118,8 +118,11 @@ gfx::Point ScreenAsh::GetCursorScreenPoint() {
return aura::Env::GetInstance()->last_mouse_location();
}
-gfx::NativeWindow ScreenAsh::GetWindowAtCursorScreenPoint() {
- const gfx::Point point = Shell::GetScreen()->GetCursorScreenPoint();
+gfx::NativeWindow ScreenAsh::GetWindowUnderCursor() {
+ return GetWindowAtScreenPoint(Shell::GetScreen()->GetCursorScreenPoint());
+}
+
+gfx::NativeWindow ScreenAsh::GetWindowAtScreenPoint(const gfx::Point& point) {
return wm::GetRootWindowAt(point)->GetTopWindowContainingPoint(point);
}
diff --git a/ash/screen_ash.h b/ash/screen_ash.h
index 95869b0..6c07607 100644
--- a/ash/screen_ash.h
+++ b/ash/screen_ash.h
@@ -65,7 +65,9 @@ class ASH_EXPORT ScreenAsh : public gfx::Screen {
// gfx::Screen overrides:
virtual bool IsDIPEnabled() OVERRIDE;
virtual gfx::Point GetCursorScreenPoint() OVERRIDE;
- virtual gfx::NativeWindow GetWindowAtCursorScreenPoint() OVERRIDE;
+ virtual gfx::NativeWindow GetWindowUnderCursor() OVERRIDE;
+ virtual gfx::NativeWindow GetWindowAtScreenPoint(const gfx::Point& point)
+ OVERRIDE;
virtual int GetNumDisplays() const OVERRIDE;
virtual std::vector<gfx::Display> GetAllDisplays() const OVERRIDE;
virtual gfx::Display GetDisplayNearestWindow(
diff --git a/chrome/browser/ui/autofill/autofill_dialog_controller_impl.cc b/chrome/browser/ui/autofill/autofill_dialog_controller_impl.cc
index 1429c6a..2c11343 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_controller_impl.cc
+++ b/chrome/browser/ui/autofill/autofill_dialog_controller_impl.cc
@@ -76,6 +76,7 @@
#include "grit/webkit_resources.h"
#include "net/cert/cert_status_flags.h"
#include "ui/base/base_window.h"
+#include "ui/base/events/event.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/models/combobox_model.h"
#include "ui/base/resource/resource_bundle.h"
@@ -1769,6 +1770,7 @@ void AutofillDialogControllerImpl::UserEditedOrActivatedInput(
content_bounds,
base::i18n::IsRTL() ?
base::i18n::RIGHT_TO_LEFT : base::i18n::LEFT_TO_RIGHT);
+ popup_controller_->set_hide_on_outside_click(true);
popup_controller_->Show(popup_values,
popup_labels,
popup_icons,
@@ -2021,6 +2023,12 @@ void AutofillDialogControllerImpl::OnPopupShown(
void AutofillDialogControllerImpl::OnPopupHidden(
content::RenderWidgetHost::KeyPressEventCallback* callback) {}
+bool AutofillDialogControllerImpl::ShouldRepostEvent(
+ const ui::MouseEvent& event) {
+ // If the event would be reposted inside |input_showing_popup_|, just ignore.
+ return !view_->HitTestInput(*input_showing_popup_, event.location());
+}
+
void AutofillDialogControllerImpl::DidSelectSuggestion(int identifier) {
// TODO(estade): implement.
}
diff --git a/chrome/browser/ui/autofill/autofill_dialog_controller_impl.h b/chrome/browser/ui/autofill/autofill_dialog_controller_impl.h
index 7513258..54fb490 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_controller_impl.h
+++ b/chrome/browser/ui/autofill/autofill_dialog_controller_impl.h
@@ -176,6 +176,7 @@ class AutofillDialogControllerImpl : public AutofillDialogViewDelegate,
content::RenderWidgetHost::KeyPressEventCallback* callback) OVERRIDE;
virtual void OnPopupHidden(
content::RenderWidgetHost::KeyPressEventCallback* callback) OVERRIDE;
+ virtual bool ShouldRepostEvent(const ui::MouseEvent& event) OVERRIDE;
virtual void DidSelectSuggestion(int identifier) OVERRIDE;
virtual void DidAcceptSuggestion(const string16& value,
int identifier) OVERRIDE;
diff --git a/chrome/browser/ui/autofill/autofill_dialog_controller_unittest.cc b/chrome/browser/ui/autofill/autofill_dialog_controller_unittest.cc
index f7d8798..7947bf30 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_controller_unittest.cc
+++ b/chrome/browser/ui/autofill/autofill_dialog_controller_unittest.cc
@@ -172,6 +172,10 @@ class TestAutofillDialogView : public AutofillDialogView {
}
virtual string16 GetCvc() OVERRIDE { return string16(); }
+ virtual bool HitTestInput(const DetailInput& input,
+ const gfx::Point& screen_point) OVERRIDE {
+ return false;
+ }
virtual bool SaveDetailsLocally() OVERRIDE { return true; }
virtual const content::NavigationController* ShowSignIn() OVERRIDE {
return NULL;
diff --git a/chrome/browser/ui/autofill/autofill_dialog_view.h b/chrome/browser/ui/autofill/autofill_dialog_view.h
index 9466c0b..295f429 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_view.h
+++ b/chrome/browser/ui/autofill/autofill_dialog_view.h
@@ -12,6 +12,7 @@ class NavigationController;
}
namespace gfx {
+class Point;
class Size;
}
@@ -78,6 +79,10 @@ class AutofillDialogView {
// relevant.
virtual string16 GetCvc() = 0;
+ // Whether or not |point| is within |input|'s bounds.
+ virtual bool HitTestInput(const DetailInput& input,
+ const gfx::Point& screen_point) = 0;
+
// Returns true if new or edited autofill details should be saved.
virtual bool SaveDetailsLocally() = 0;
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller.h b/chrome/browser/ui/autofill/autofill_popup_controller.h
index 63a7549..4b4f7c6 100644
--- a/chrome/browser/ui/autofill/autofill_popup_controller.h
+++ b/chrome/browser/ui/autofill/autofill_popup_controller.h
@@ -18,6 +18,10 @@ class Rect;
class RectF;
}
+namespace ui {
+class MouseEvent;
+}
+
namespace autofill {
// This interface provides data to an AutofillPopupView.
@@ -41,6 +45,9 @@ class AutofillPopupController {
// The user has moved the mouse outside of the popup.
virtual void MouseExitedPopup() = 0;
+ // Whether |event| should be reposted to the native window management.
+ virtual bool ShouldRepostEvent(const ui::MouseEvent& event) = 0;
+
// Accepts the suggestion at |index|.
virtual void AcceptSuggestion(size_t index) = 0;
@@ -100,6 +107,9 @@ class AutofillPopupController {
// hovered or has keyboard focus.
virtual int selected_line() const = 0;
+ // Whether the view should be hidden on outside mouse presses.
+ virtual bool hide_on_outside_click() const = 0;
+
protected:
virtual ~AutofillPopupController() {}
};
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc b/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
index f6ed33a..043e8c1 100644
--- a/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
+++ b/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
@@ -100,6 +100,7 @@ AutofillPopupControllerImpl::AutofillPopupControllerImpl(
container_view_(container_view),
element_bounds_(element_bounds),
text_direction_(text_direction),
+ hide_on_outside_click_(false),
weak_ptr_factory_(this),
key_press_event_callback_(
base::Bind(&AutofillPopupControllerImpl::HandleKeyPressEvent,
@@ -305,6 +306,11 @@ void AutofillPopupControllerImpl::MouseExitedPopup() {
SetSelectedLine(kNoSelection);
}
+bool AutofillPopupControllerImpl::ShouldRepostEvent(
+ const ui::MouseEvent& event) {
+ return delegate_->ShouldRepostEvent(event);
+}
+
void AutofillPopupControllerImpl::AcceptSuggestion(size_t index) {
delegate_->DidAcceptSuggestion(full_names_[index], identifiers_[index]);
}
@@ -366,6 +372,10 @@ bool AutofillPopupControllerImpl::IsRTL() const {
return text_direction_ == base::i18n::RIGHT_TO_LEFT;
}
+bool AutofillPopupControllerImpl::hide_on_outside_click() const {
+ return hide_on_outside_click_;
+}
+
const std::vector<string16>& AutofillPopupControllerImpl::names() const {
return names_;
}
@@ -400,6 +410,11 @@ int AutofillPopupControllerImpl::selected_line() const {
return selected_line_;
}
+void AutofillPopupControllerImpl::set_hide_on_outside_click(
+ bool hide_on_outside_click) {
+ hide_on_outside_click_ = hide_on_outside_click;
+}
+
void AutofillPopupControllerImpl::SetSelectedLine(int selected_line) {
if (selected_line_ == selected_line)
return;
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_impl.h b/chrome/browser/ui/autofill/autofill_popup_controller_impl.h
index a7697c8..43f5a1d 100644
--- a/chrome/browser/ui/autofill/autofill_popup_controller_impl.h
+++ b/chrome/browser/ui/autofill/autofill_popup_controller_impl.h
@@ -66,6 +66,9 @@ class AutofillPopupControllerImpl : public AutofillPopupController {
bool HandleKeyPressEvent(const content::NativeWebKeyboardEvent& event);
+ // Tells the view to capture mouse events. Must be called before |Show()|.
+ void set_hide_on_outside_click(bool hide_on_outside_click);
+
protected:
FRIEND_TEST_ALL_PREFIXES(AutofillExternalDelegateBrowserTest,
CloseWidgetAndNoLeaking);
@@ -83,6 +86,7 @@ class AutofillPopupControllerImpl : public AutofillPopupController {
virtual void MouseHovered(int x, int y) OVERRIDE;
virtual void MouseClicked(int x, int y) OVERRIDE;
virtual void MouseExitedPopup() OVERRIDE;
+ virtual bool ShouldRepostEvent(const ui::MouseEvent& event) OVERRIDE;
virtual void AcceptSuggestion(size_t index) OVERRIDE;
virtual int GetIconResourceID(const string16& resource_name) OVERRIDE;
virtual bool CanDelete(size_t index) const OVERRIDE;
@@ -103,6 +107,7 @@ class AutofillPopupControllerImpl : public AutofillPopupController {
virtual const gfx::Font& subtext_font() const OVERRIDE;
#endif
virtual int selected_line() const OVERRIDE;
+ virtual bool hide_on_outside_click() const OVERRIDE;
// Change which line is currently selected by the user.
void SetSelectedLine(int selected_line);
@@ -225,6 +230,9 @@ class AutofillPopupControllerImpl : public AutofillPopupController {
// |kNoSelection| indicates that no line is currently selected.
int selected_line_;
+ // Whether the popup view should hide on mouse presses outside of it.
+ bool hide_on_outside_click_;
+
base::WeakPtrFactory<AutofillPopupControllerImpl> weak_ptr_factory_;
content::RenderWidgetHost::KeyPressEventCallback key_press_event_callback_;
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_dialog_cocoa.h b/chrome/browser/ui/cocoa/autofill/autofill_dialog_cocoa.h
index 077fb64..00149bc 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_dialog_cocoa.h
+++ b/chrome/browser/ui/cocoa/autofill/autofill_dialog_cocoa.h
@@ -54,6 +54,8 @@ class AutofillDialogCocoa : public AutofillDialogView,
virtual void GetUserInput(DialogSection section,
DetailOutputMap* output) OVERRIDE;
virtual string16 GetCvc() OVERRIDE;
+ virtual bool HitTestInput(const DetailInput& input,
+ const gfx::Point& screen_point) OVERRIDE;
virtual bool SaveDetailsLocally() OVERRIDE;
virtual const content::NavigationController* ShowSignIn() OVERRIDE;
virtual void HideSignIn() OVERRIDE;
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_dialog_cocoa.mm b/chrome/browser/ui/cocoa/autofill/autofill_dialog_cocoa.mm
index f048320..fc40da2 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_dialog_cocoa.mm
+++ b/chrome/browser/ui/cocoa/autofill/autofill_dialog_cocoa.mm
@@ -128,6 +128,12 @@ string16 AutofillDialogCocoa::GetCvc() {
return string16();
}
+bool AutofillDialogCocoa::HitTestInput(const DetailInput& input,
+ const gfx::Point& screen_point) {
+ // TODO(dbeam): implement.
+ return false;
+}
+
bool AutofillDialogCocoa::SaveDetailsLocally() {
return [sheet_delegate_ saveDetailsLocally];
}
diff --git a/chrome/browser/ui/views/autofill/autofill_dialog_views.cc b/chrome/browser/ui/views/autofill/autofill_dialog_views.cc
index 9ba8e46..c9be835 100644
--- a/chrome/browser/ui/views/autofill/autofill_dialog_views.cc
+++ b/chrome/browser/ui/views/autofill/autofill_dialog_views.cc
@@ -7,6 +7,7 @@
#include <utility>
#include "base/bind.h"
+#include "base/location.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/autofill/autofill_dialog_sign_in_delegate.h"
@@ -32,6 +33,7 @@
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/path.h"
+#include "ui/gfx/point.h"
#include "ui/gfx/skia_util.h"
#include "ui/views/background.h"
#include "ui/views/border.h"
@@ -1429,6 +1431,22 @@ base::string16 AutofillDialogViews::GetCvc() {
decorated_textfield()->text();
}
+bool AutofillDialogViews::HitTestInput(const DetailInput& input,
+ const gfx::Point& screen_point) {
+ views::View* view = TextfieldForInput(input);
+ if (!view)
+ view = ComboboxForInput(input);
+
+ if (view) {
+ gfx::Point target_point(screen_point);
+ views::View::ConvertPointFromScreen(view, &target_point);
+ return view->HitTestPoint(target_point);
+ }
+
+ NOTREACHED();
+ return false;
+}
+
bool AutofillDialogViews::SaveDetailsLocally() {
DCHECK(save_in_chrome_checkbox_->visible());
return save_in_chrome_checkbox_->checked();
@@ -2270,11 +2288,11 @@ void AutofillDialogViews::TextfieldEditedOrActivated(
decorated = iter->second;
if (decorated == textfield) {
delegate_->UserEditedOrActivatedInput(group->section,
- iter->first,
- GetWidget()->GetNativeView(),
- textfield->GetBoundsInScreen(),
- textfield->text(),
- was_edit);
+ iter->first,
+ GetWidget()->GetNativeView(),
+ textfield->GetBoundsInScreen(),
+ textfield->text(),
+ was_edit);
type = iter->first->type;
break;
}
diff --git a/chrome/browser/ui/views/autofill/autofill_dialog_views.h b/chrome/browser/ui/views/autofill/autofill_dialog_views.h
index 1f660eb..c5b37c4 100644
--- a/chrome/browser/ui/views/autofill/autofill_dialog_views.h
+++ b/chrome/browser/ui/views/autofill/autofill_dialog_views.h
@@ -92,6 +92,8 @@ class AutofillDialogViews : public AutofillDialogView,
virtual void GetUserInput(DialogSection section,
DetailOutputMap* output) OVERRIDE;
virtual base::string16 GetCvc() OVERRIDE;
+ virtual bool HitTestInput(const DetailInput& input,
+ const gfx::Point& screen_point) OVERRIDE;
virtual bool SaveDetailsLocally() OVERRIDE;
virtual const content::NavigationController* ShowSignIn() OVERRIDE;
virtual void HideSignIn() OVERRIDE;
diff --git a/chrome/browser/ui/views/autofill/autofill_popup_view_views.cc b/chrome/browser/ui/views/autofill/autofill_popup_view_views.cc
index 661ef09..2c725f5 100644
--- a/chrome/browser/ui/views/autofill/autofill_popup_view_views.cc
+++ b/chrome/browser/ui/views/autofill/autofill_popup_view_views.cc
@@ -11,9 +11,12 @@
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/image/image.h"
+#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/point.h"
#include "ui/gfx/rect.h"
+#include "ui/gfx/screen.h"
#include "ui/views/border.h"
+#include "ui/views/event_utils.h"
#include "ui/views/widget/widget.h"
using WebKit::WebAutofillClient;
@@ -108,28 +111,61 @@ void AutofillPopupViewViews::OnMouseExited(const ui::MouseEvent& event) {
}
void AutofillPopupViewViews::OnMouseMoved(const ui::MouseEvent& event) {
- if (controller_)
+ if (!controller_)
+ return;
+
+ if (HitTestPoint(event.location()))
controller_->MouseHovered(event.x(), event.y());
+ else
+ controller_->MouseExitedPopup();
}
bool AutofillPopupViewViews::OnMousePressed(const ui::MouseEvent& event) {
- // We must return true in order to get the OnMouseReleased event later.
- return true;
+ if (HitTestPoint(event.location()))
+ return true;
+
+ if (controller_->hide_on_outside_click()) {
+ GetWidget()->ReleaseCapture();
+
+ gfx::Point screen_loc = event.location();
+ views::View::ConvertPointToScreen(this, &screen_loc);
+
+ ui::MouseEvent mouse_event = event;
+ mouse_event.set_location(screen_loc);
+
+ if (controller_->ShouldRepostEvent(mouse_event)) {
+ gfx::NativeView native_view = GetWidget()->GetNativeView();
+ gfx::Screen* screen = gfx::Screen::GetScreenFor(native_view);
+ gfx::NativeWindow window = screen->GetWindowAtScreenPoint(screen_loc);
+ views::RepostLocatedEvent(window, mouse_event);
+ }
+
+ controller_->Hide();
+ // |this| is now deleted.
+ }
+
+ return false;
}
void AutofillPopupViewViews::OnMouseReleased(const ui::MouseEvent& event) {
if (!controller_)
return;
+ // Because this view can can be shown in response to a mouse press, it can
+ // receive an OnMouseReleased event just after showing. This breaks the mouse
+ // capture, so restart capturing here.
+ if (controller_->hide_on_outside_click() && GetWidget())
+ GetWidget()->SetCapture(this);
+
// We only care about the left click.
- if (event.IsOnlyLeftMouseButton() &&
- HitTestPoint(event.location()))
+ if (event.IsOnlyLeftMouseButton() && HitTestPoint(event.location()))
controller_->MouseClicked(event.x(), event.y());
}
void AutofillPopupViewViews::OnWidgetBoundsChanged(
views::Widget* widget,
const gfx::Rect& new_bounds) {
+ DCHECK_EQ(widget, observing_widget_);
controller_->Hide();
}
@@ -152,6 +188,9 @@ void AutofillPopupViewViews::Show() {
UpdateBoundsAndRedrawPopup();
GetWidget()->Show();
+
+ if (controller_->hide_on_outside_click())
+ GetWidget()->SetCapture(this);
}
void AutofillPopupViewViews::InvalidateRow(size_t row) {
diff --git a/chrome/browser/ui/views/panels/panel_view.cc b/chrome/browser/ui/views/panels/panel_view.cc
index d122392e..fb765f1 100644
--- a/chrome/browser/ui/views/panels/panel_view.cc
+++ b/chrome/browser/ui/views/panels/panel_view.cc
@@ -973,7 +973,7 @@ void PanelView::OnWidgetActivationChanged(views::Widget* widget, bool active) {
if (focused_ && panel_->IsMinimized() &&
panel_->collection()->type() == PanelCollection::DOCKED &&
gfx::Screen::GetScreenFor(widget->GetNativeWindow())->
- GetWindowAtCursorScreenPoint() != widget->GetNativeWindow()) {
+ GetWindowUnderCursor() != widget->GetNativeWindow()) {
panel_->Restore();
}
#endif
diff --git a/chrome/browser/ui/window_sizer/window_sizer_common_unittest.cc b/chrome/browser/ui/window_sizer/window_sizer_common_unittest.cc
index 6f4bd8d..f0984a5 100644
--- a/chrome/browser/ui/window_sizer/window_sizer_common_unittest.cc
+++ b/chrome/browser/ui/window_sizer/window_sizer_common_unittest.cc
@@ -31,7 +31,13 @@ class TestScreen : public gfx::Screen {
return gfx::Point();
}
- virtual gfx::NativeWindow GetWindowAtCursorScreenPoint() OVERRIDE {
+ virtual gfx::NativeWindow GetWindowUnderCursor() OVERRIDE {
+ NOTREACHED();
+ return NULL;
+ }
+
+ virtual gfx::NativeWindow GetWindowAtScreenPoint(const gfx::Point& point)
+ OVERRIDE {
NOTREACHED();
return NULL;
}
diff --git a/components/autofill/core/browser/autofill_external_delegate.cc b/components/autofill/core/browser/autofill_external_delegate.cc
index b5d38d4..ca6696e 100644
--- a/components/autofill/core/browser/autofill_external_delegate.cc
+++ b/components/autofill/core/browser/autofill_external_delegate.cc
@@ -186,6 +186,11 @@ void AutofillExternalDelegate::OnPopupHidden(
registered_key_press_event_callback_with_ = NULL;
}
+bool AutofillExternalDelegate::ShouldRepostEvent(const ui::MouseEvent& event) {
+ NOTREACHED();
+ return true;
+}
+
void AutofillExternalDelegate::DidSelectSuggestion(int identifier) {
ClearPreviewedForm();
diff --git a/components/autofill/core/browser/autofill_external_delegate.h b/components/autofill/core/browser/autofill_external_delegate.h
index 433027e..0a0093e 100644
--- a/components/autofill/core/browser/autofill_external_delegate.h
+++ b/components/autofill/core/browser/autofill_external_delegate.h
@@ -51,6 +51,7 @@ class AutofillExternalDelegate
content::RenderWidgetHost::KeyPressEventCallback* callback) OVERRIDE;
virtual void OnPopupHidden(
content::RenderWidgetHost::KeyPressEventCallback* callback) OVERRIDE;
+ virtual bool ShouldRepostEvent(const ui::MouseEvent& event) OVERRIDE;
virtual void DidSelectSuggestion(int identifier) OVERRIDE;
virtual void DidAcceptSuggestion(const base::string16& value,
int identifier) OVERRIDE;
diff --git a/components/autofill/core/browser/autofill_popup_delegate.h b/components/autofill/core/browser/autofill_popup_delegate.h
index 0f2ab41..86b5eff 100644
--- a/components/autofill/core/browser/autofill_popup_delegate.h
+++ b/components/autofill/core/browser/autofill_popup_delegate.h
@@ -8,6 +8,10 @@
#include "base/strings/string16.h"
#include "content/public/browser/render_view_host.h"
+namespace ui {
+class MouseEvent;
+}
+
namespace autofill {
// An interface for interaction with AutofillPopupController. Will be notified
@@ -24,6 +28,10 @@ class AutofillPopupDelegate {
virtual void OnPopupHidden(
content::RenderWidgetHost::KeyPressEventCallback* callback) = 0;
+ // Called when the Autofill popup recieves a click outside of the popup view
+ // to determine if the event should be reposted to the native window manager.
+ virtual bool ShouldRepostEvent(const ui::MouseEvent& event) = 0;
+
// Called when the autofill suggestion indicated by |identifier| has been
// temporarily selected (e.g., hovered).
virtual void DidSelectSuggestion(int identifier) = 0;
diff --git a/ui/aura/test/test_screen.cc b/ui/aura/test/test_screen.cc
index 474ac29..c43ffb4 100644
--- a/ui/aura/test/test_screen.cc
+++ b/ui/aura/test/test_screen.cc
@@ -108,8 +108,11 @@ gfx::Point TestScreen::GetCursorScreenPoint() {
return Env::GetInstance()->last_mouse_location();
}
-gfx::NativeWindow TestScreen::GetWindowAtCursorScreenPoint() {
- const gfx::Point point = GetCursorScreenPoint();
+gfx::NativeWindow TestScreen::GetWindowUnderCursor() {
+ return GetWindowAtScreenPoint(GetCursorScreenPoint());
+}
+
+gfx::NativeWindow TestScreen::GetWindowAtScreenPoint(const gfx::Point& point) {
return root_window_->GetTopWindowContainingPoint(point);
}
diff --git a/ui/aura/test/test_screen.h b/ui/aura/test/test_screen.h
index 00d684b..c958279 100644
--- a/ui/aura/test/test_screen.h
+++ b/ui/aura/test/test_screen.h
@@ -47,7 +47,9 @@ class TestScreen : public gfx::Screen,
// gfx::Screen overrides:
virtual bool IsDIPEnabled() OVERRIDE;
virtual gfx::Point GetCursorScreenPoint() OVERRIDE;
- virtual gfx::NativeWindow GetWindowAtCursorScreenPoint() OVERRIDE;
+ virtual gfx::NativeWindow GetWindowUnderCursor() OVERRIDE;
+ virtual gfx::NativeWindow GetWindowAtScreenPoint(const gfx::Point& point)
+ OVERRIDE;
virtual int GetNumDisplays() const OVERRIDE;
virtual std::vector<gfx::Display> GetAllDisplays() const OVERRIDE;
virtual gfx::Display GetDisplayNearestWindow(
diff --git a/ui/gfx/screen.h b/ui/gfx/screen.h
index 7958f65..d94e3e0 100644
--- a/ui/gfx/screen.h
+++ b/ui/gfx/screen.h
@@ -52,7 +52,10 @@ class UI_EXPORT Screen {
virtual gfx::Point GetCursorScreenPoint() = 0;
// Returns the window under the cursor.
- virtual gfx::NativeWindow GetWindowAtCursorScreenPoint() = 0;
+ virtual gfx::NativeWindow GetWindowUnderCursor() = 0;
+
+ // Returns the window at the given screen coordinate |point|.
+ virtual gfx::NativeWindow GetWindowAtScreenPoint(const gfx::Point& point) = 0;
// Returns the number of displays.
// Mirrored displays are excluded; this method is intended to return the
@@ -65,7 +68,7 @@ class UI_EXPORT Screen {
// Returns the display nearest the specified window.
virtual gfx::Display GetDisplayNearestWindow(NativeView view) const = 0;
- // Returns the the display nearest the specified point.
+ // Returns the display nearest the specified point.
virtual gfx::Display GetDisplayNearestPoint(
const gfx::Point& point) const = 0;
diff --git a/ui/gfx/screen_android.cc b/ui/gfx/screen_android.cc
index 1376136..e90bb76 100644
--- a/ui/gfx/screen_android.cc
+++ b/ui/gfx/screen_android.cc
@@ -19,7 +19,13 @@ class ScreenAndroid : public Screen {
virtual gfx::Point GetCursorScreenPoint() OVERRIDE { return gfx::Point(); }
- virtual gfx::NativeWindow GetWindowAtCursorScreenPoint() OVERRIDE {
+ virtual gfx::NativeWindow GetWindowUnderCursor() OVERRIDE {
+ NOTIMPLEMENTED();
+ return NULL;
+ }
+
+ virtual gfx::NativeWindow GetWindowAtScreenPoint(const gfx::Point& point)
+ OVERRIDE {
NOTIMPLEMENTED();
return NULL;
}
diff --git a/ui/gfx/screen_gtk.cc b/ui/gfx/screen_gtk.cc
index 5177dc9..16a7873 100644
--- a/ui/gfx/screen_gtk.cc
+++ b/ui/gfx/screen_gtk.cc
@@ -91,7 +91,7 @@ class ScreenGtk : public gfx::Screen {
}
// Returns the window under the cursor.
- virtual gfx::NativeWindow GetWindowAtCursorScreenPoint() OVERRIDE {
+ virtual gfx::NativeWindow GetWindowUnderCursor() OVERRIDE {
GdkWindow* window = gdk_window_at_pointer(NULL, NULL);
if (!window)
return NULL;
@@ -105,6 +105,12 @@ class ScreenGtk : public gfx::Screen {
return GTK_IS_WINDOW(widget) ? GTK_WINDOW(widget) : NULL;
}
+ virtual gfx::NativeWindow GetWindowAtScreenPoint(const gfx::Point& point)
+ OVERRIDE {
+ NOTIMPLEMENTED();
+ return NULL;
+ }
+
// Returns the number of displays.
// Mirrored displays are excluded; this method is intended to return the
// number of distinct, usable displays.
diff --git a/ui/gfx/screen_ios.mm b/ui/gfx/screen_ios.mm
index 6450e14..a277029 100644
--- a/ui/gfx/screen_ios.mm
+++ b/ui/gfx/screen_ios.mm
@@ -21,7 +21,13 @@ class ScreenIos : public gfx::Screen {
return gfx::Point(0, 0);
}
- virtual gfx::NativeWindow GetWindowAtCursorScreenPoint() OVERRIDE {
+ virtual gfx::NativeWindow GetWindowUnderCursor() OVERRIDE {
+ NOTIMPLEMENTED();
+ return gfx::NativeWindow();
+ }
+
+ virtual gfx::NativeWindow GetWindowAtScreenPoint(const gfx::Point& point)
+ OVERRIDE {
NOTIMPLEMENTED();
return gfx::NativeWindow();
}
diff --git a/ui/gfx/screen_mac.mm b/ui/gfx/screen_mac.mm
index 8f85ae6..28707ca 100644
--- a/ui/gfx/screen_mac.mm
+++ b/ui/gfx/screen_mac.mm
@@ -84,7 +84,13 @@ class ScreenMac : public gfx::Screen {
return gfx::Point(mouseLocation.x, mouseLocation.y);
}
- virtual gfx::NativeWindow GetWindowAtCursorScreenPoint() OVERRIDE {
+ virtual gfx::NativeWindow GetWindowUnderCursor() OVERRIDE {
+ NOTIMPLEMENTED();
+ return gfx::NativeWindow();
+ }
+
+ virtual gfx::NativeWindow GetWindowAtScreenPoint(const gfx::Point& point)
+ OVERRIDE {
NOTIMPLEMENTED();
return gfx::NativeWindow();
}
diff --git a/ui/gfx/screen_win.cc b/ui/gfx/screen_win.cc
index 23dbc9d..95847c4 100644
--- a/ui/gfx/screen_win.cc
+++ b/ui/gfx/screen_win.cc
@@ -49,10 +49,14 @@ gfx::Point ScreenWin::GetCursorScreenPoint() {
return gfx::Point(pt);
}
-gfx::NativeWindow ScreenWin::GetWindowAtCursorScreenPoint() {
- POINT location;
- HWND window_hwnd = GetCursorPos(&location) ? WindowFromPoint(location) : NULL;
- return GetNativeWindowFromHWND(window_hwnd);
+gfx::NativeWindow ScreenWin::GetWindowUnderCursor() {
+ POINT cursor_loc;
+ HWND hwnd = GetCursorPos(&cursor_loc) ? WindowFromPoint(cursor_loc) : NULL;
+ return GetNativeWindowFromHWND(hwnd);
+}
+
+gfx::NativeWindow ScreenWin::GetWindowAtScreenPoint(const gfx::Point& point) {
+ return GetNativeWindowFromHWND(WindowFromPoint(point.ToPOINT()));
}
int ScreenWin::GetNumDisplays() const {
diff --git a/ui/gfx/screen_win.h b/ui/gfx/screen_win.h
index cc59352..8905d46 100644
--- a/ui/gfx/screen_win.h
+++ b/ui/gfx/screen_win.h
@@ -20,7 +20,9 @@ class UI_EXPORT ScreenWin : public gfx::Screen {
// Overridden from gfx::Screen:
virtual bool IsDIPEnabled() OVERRIDE;
virtual gfx::Point GetCursorScreenPoint() OVERRIDE;
- virtual gfx::NativeWindow GetWindowAtCursorScreenPoint() OVERRIDE;
+ virtual gfx::NativeWindow GetWindowUnderCursor() OVERRIDE;
+ virtual gfx::NativeWindow GetWindowAtScreenPoint(const gfx::Point& point)
+ OVERRIDE;
virtual int GetNumDisplays() const OVERRIDE;
virtual std::vector<gfx::Display> GetAllDisplays() const OVERRIDE;
virtual gfx::Display GetDisplayNearestWindow(
diff --git a/ui/views/controls/menu/menu_controller.cc b/ui/views/controls/menu/menu_controller.cc
index 80eacad..b2a2574 100644
--- a/ui/views/controls/menu/menu_controller.cc
+++ b/ui/views/controls/menu/menu_controller.cc
@@ -20,6 +20,7 @@
#include "ui/base/keycodes/keyboard_codes.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/canvas.h"
+#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/screen.h"
#include "ui/gfx/vector2d.h"
#include "ui/native_theme/native_theme.h"
@@ -30,6 +31,7 @@
#include "ui/views/controls/menu/menu_scroll_view_container.h"
#include "ui/views/controls/menu/submenu_view.h"
#include "ui/views/drag_utils.h"
+#include "ui/views/event_utils.h"
#include "ui/views/mouse_constants.h"
#include "ui/views/view_constants.h"
#include "ui/views/views_delegate.h"
@@ -39,7 +41,6 @@
#if defined(USE_AURA)
#include "ui/aura/env.h"
#include "ui/aura/root_window.h"
-#include "ui/aura/window.h"
#endif
#if defined(OS_WIN)
@@ -890,9 +891,15 @@ void MenuController::SetSelectionOnPointerDown(SubmenuView* source,
#if defined(OS_WIN)
// We're going to close and we own the mouse capture. We need to repost the
- // mouse down, otherwise the window the user clicked on won't get the
- // event.
- RepostEvent(source, event);
+ // mouse down, otherwise the window the user clicked on won't get the event.
+ if (!state_.item) {
+ // We some times get an event after closing all the menus. Ignore it. Make
+ // sure the menu is in fact not visible. If the menu is visible, then
+ // we're in a bad state where we think the menu isn't visibile but it is.
+ DCHECK(!source->GetWidget()->IsVisible());
+ } else {
+ RepostEvent(source, event);
+ }
#endif
// And close.
@@ -1253,8 +1260,7 @@ bool MenuController::ShowSiblingMenu(SubmenuView* source,
return false;
}
- gfx::NativeWindow window_under_mouse =
- GetScreen()->GetWindowAtCursorScreenPoint();
+ gfx::NativeWindow window_under_mouse = GetScreen()->GetWindowUnderCursor();
// TODO(oshima): Replace with views only API.
if (!owner_ || window_under_mouse != owner_->GetNativeWindow())
return false;
@@ -2093,94 +2099,52 @@ bool MenuController::SelectByChar(char16 character) {
return false;
}
-#if defined(OS_WIN)
void MenuController::RepostEvent(SubmenuView* source,
const ui::LocatedEvent& event) {
- if (!state_.item) {
- // We some times get an event after closing all the menus. Ignore it.
- // Make sure the menu is in fact not visible. If the menu is visible, then
- // we're in a bad state where we think the menu isn't visibile but it is.
- DCHECK(!source->GetWidget()->IsVisible());
- return;
- }
-
gfx::Point screen_loc(event.location());
View::ConvertPointToScreen(source->GetScrollViewContainer(), &screen_loc);
- HWND window = WindowFromPoint(screen_loc.ToPOINT());
- if (window) {
- // Release the capture.
- SubmenuView* submenu = state_.item->GetRootMenuItem()->GetSubmenu();
- submenu->ReleaseCapture();
-
- if (submenu->GetWidget()->GetNativeView() &&
- GetWindowThreadProcessId(
- HWNDForNativeView(submenu->GetWidget()->GetNativeView()), NULL) !=
- GetWindowThreadProcessId(window, NULL)) {
- // Even though we have mouse capture, windows generates a mouse event
- // if the other window is in a separate thread. Don't generate an event in
- // this case else the target window can get double events leading to bad
- // behavior.
- return;
- }
- // Convert the coordinates to the target window.
- RECT window_bounds;
- GetWindowRect(window, &window_bounds);
- int window_x = screen_loc.x() - window_bounds.left;
- int window_y = screen_loc.y() - window_bounds.top;
-
- // Determine whether the click was in the client area or not.
- // NOTE: WM_NCHITTEST coordinates are relative to the screen.
- LRESULT nc_hit_result = SendMessage(window, WM_NCHITTEST, 0,
- MAKELPARAM(screen_loc.x(),
- screen_loc.y()));
- const bool in_client_area = (nc_hit_result == HTCLIENT);
-
- // TODO(sky): this isn't right. The event to generate should correspond
- // with the event we just got. MouseEvent only tells us what is down,
- // which may differ. Need to add ability to get changed button from
- // MouseEvent.
- int event_type;
- int flags = event.flags();
- if (flags & ui::EF_LEFT_MOUSE_BUTTON)
- event_type = in_client_area ? WM_LBUTTONDOWN : WM_NCLBUTTONDOWN;
- else if (flags & ui::EF_MIDDLE_MOUSE_BUTTON)
- event_type = in_client_area ? WM_MBUTTONDOWN : WM_NCMBUTTONDOWN;
- else if (flags & ui::EF_RIGHT_MOUSE_BUTTON)
- event_type = in_client_area ? WM_RBUTTONDOWN : WM_NCRBUTTONDOWN;
- else
- event_type = 0; // Unknown mouse press.
+ gfx::NativeView native_view = source->GetWidget()->GetNativeView();
+ gfx::Screen* screen = gfx::Screen::GetScreenFor(native_view);
+ gfx::NativeWindow window = screen->GetWindowAtScreenPoint(screen_loc);
- if (event_type) {
- if (in_client_area) {
- PostMessage(window, event_type, event.native_event().wParam,
- MAKELPARAM(window_x, window_y));
- } else {
- PostMessage(window, event_type, nc_hit_result,
- MAKELPARAM(screen_loc.x(), screen_loc.y()));
- }
- } else if (event.type() == ui::ET_GESTURE_TAP_DOWN) {
-#if defined(USE_AURA)
- // Gesture events need to be posted to the target root window. In
- // desktop chrome there could be multiple root windows.
- aura::RootWindow* target_root =
- aura::RootWindow::GetForAcceleratedWidget(window);
- if (target_root)
- target_root->RepostEvent(event);
-#endif
+ if (!window)
+ return;
+
+#if defined(OS_WIN)
+ // Release the capture.
+ SubmenuView* submenu = state_.item->GetRootMenuItem()->GetSubmenu();
+ submenu->ReleaseCapture();
+
+ gfx::NativeView view = submenu->GetWidget()->GetNativeView();
+ if (view) {
+ DWORD view_tid = GetWindowThreadProcessId(HWNDForNativeView(view), NULL);
+ if (view_tid != GetWindowThreadProcessId(HWNDForNativeView(window), NULL)) {
+ // Even though we have mouse capture, windows generates a mouse event if
+ // the other window is in a separate thread. Only repost an event if
+ // |view| was created on the same thread, else the target window can get
+ // double events leading to bad behavior.
+ return;
}
}
-}
-#elif defined(USE_AURA)
-void MenuController::RepostEvent(SubmenuView* source,
- const ui::LocatedEvent& event) {
- aura::RootWindow* root_window =
- source->GetWidget()->GetNativeWindow()->GetRootWindow();
- DCHECK(root_window);
- root_window->RepostEvent(event);
-}
#endif
+ scoped_ptr<ui::LocatedEvent> clone;
+ if (event.IsMouseEvent()) {
+ clone.reset(new ui::MouseEvent(static_cast<const ui::MouseEvent&>(event)));
+ } else if (event.IsGestureEvent()) {
+ const ui::GestureEvent& ge = static_cast<const ui::GestureEvent&>(event);
+ clone.reset(new ui::GestureEvent(ge));
+ } else {
+ NOTREACHED();
+ return;
+ }
+ clone->set_location(screen_loc);
+
+ RepostLocatedEvent(window, *clone);
+}
+
+
void MenuController::SetDropMenuItem(
MenuItemView* new_target,
MenuDelegate::DropPosition new_position) {
diff --git a/ui/views/event_utils.h b/ui/views/event_utils.h
new file mode 100644
index 0000000..3527c50
--- /dev/null
+++ b/ui/views/event_utils.h
@@ -0,0 +1,25 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_EVENT_UTILS_H_
+#define UI_VIEWS_EVENT_UTILS_H_
+
+#include "ui/gfx/native_widget_types.h"
+#include "ui/views/views_export.h"
+
+namespace ui {
+class LocatedEvent;
+}
+
+namespace views {
+
+// Reposts a located event natively. Returns false when |event| could not be
+// reposted. |event| should be in screen coordinates. |window| is the target
+// window that the event will be forwarded to. Only some events are supported.
+VIEWS_EXPORT bool RepostLocatedEvent(gfx::NativeWindow window,
+ const ui::LocatedEvent& event);
+
+} // namespace views
+
+#endif // UI_VIEWS_EVENT_UTILS_H_
diff --git a/ui/views/event_utils_aura.cc b/ui/views/event_utils_aura.cc
new file mode 100644
index 0000000..37aeb88
--- /dev/null
+++ b/ui/views/event_utils_aura.cc
@@ -0,0 +1,49 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/event_utils.h"
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "ui/aura/client/screen_position_client.h"
+#include "ui/aura/root_window.h"
+#include "ui/base/events/event.h"
+#include "ui/gfx/point.h"
+
+using aura::client::ScreenPositionClient;
+
+namespace views {
+
+bool RepostLocatedEvent(gfx::NativeWindow window,
+ const ui::LocatedEvent& event) {
+ if (!window)
+ return false;
+
+ aura::RootWindow* root_window = window->GetRootWindow();
+
+ gfx::Point root_loc(event.location());
+ ScreenPositionClient* spc = GetScreenPositionClient(root_window);
+ if (!spc)
+ return false;
+
+ spc->ConvertPointFromScreen(root_window, &root_loc);
+
+ scoped_ptr<ui::LocatedEvent> relocated;
+ if (event.IsMouseEvent()) {
+ const ui::MouseEvent& orig = static_cast<const ui::MouseEvent&>(event);
+ relocated.reset(new ui::MouseEvent(orig));
+ } else if (event.IsGestureEvent()) {
+ const ui::GestureEvent& orig = static_cast<const ui::GestureEvent&>(event);
+ relocated.reset(new ui::GestureEvent(orig));
+ } else {
+ NOTREACHED();
+ return false;
+ }
+ relocated->set_location(root_loc);
+
+ root_window->RepostEvent(*relocated);
+ return true;
+}
+
+} // namespace views
diff --git a/ui/views/event_utils_win.cc b/ui/views/event_utils_win.cc
new file mode 100644
index 0000000..d9417a2e
--- /dev/null
+++ b/ui/views/event_utils_win.cc
@@ -0,0 +1,59 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/event_utils.h"
+
+#include <windowsx.h>
+
+#include "base/logging.h"
+#include "ui/base/events/event.h"
+#include "ui/base/events/event_constants.h"
+#include "ui/gfx/point.h"
+
+namespace views {
+
+bool RepostLocatedEvent(gfx::NativeWindow window,
+ const ui::LocatedEvent& event) {
+ if (!window)
+ return false;
+
+ // Determine whether the click was in the client area or not.
+ // NOTE: WM_NCHITTEST coordinates are relative to the screen.
+ const gfx::Point screen_loc = event.location();
+ LRESULT nc_hit_result = SendMessage(window, WM_NCHITTEST, 0,
+ MAKELPARAM(screen_loc.x(),
+ screen_loc.y()));
+ const bool in_client_area = nc_hit_result == HTCLIENT;
+
+ // TODO(sky): this isn't right. The event to generate should correspond with
+ // the event we just got. MouseEvent only tells us what is down, which may
+ // differ. Need to add ability to get changed button from MouseEvent.
+ int event_type;
+ int flags = event.flags();
+ if (flags & ui::EF_LEFT_MOUSE_BUTTON) {
+ event_type = in_client_area ? WM_LBUTTONDOWN : WM_NCLBUTTONDOWN;
+ } else if (flags & ui::EF_MIDDLE_MOUSE_BUTTON) {
+ event_type = in_client_area ? WM_MBUTTONDOWN : WM_NCMBUTTONDOWN;
+ } else if (flags & ui::EF_RIGHT_MOUSE_BUTTON) {
+ event_type = in_client_area ? WM_RBUTTONDOWN : WM_NCRBUTTONDOWN;
+ } else {
+ NOTREACHED();
+ return false;
+ }
+
+ int window_x = screen_loc.x();
+ int window_y = screen_loc.y();
+ if (in_client_area) {
+ RECT window_bounds;
+ GetWindowRect(window, &window_bounds);
+ window_x -= window_bounds.left;
+ window_y -= window_bounds.top;
+ }
+
+ WPARAM target = in_client_area ? event.native_event().wParam : nc_hit_result;
+ PostMessage(window, event_type, target, MAKELPARAM(window_x, window_y));
+ return true;
+}
+
+} // namespace views
diff --git a/ui/views/mouse_watcher_view_host.cc b/ui/views/mouse_watcher_view_host.cc
index 1d420fa..54412cf 100644
--- a/ui/views/mouse_watcher_view_host.cc
+++ b/ui/views/mouse_watcher_view_host.cc
@@ -50,7 +50,7 @@ bool MouseWatcherViewHost::IsMouseOverWindow() {
return false;
return gfx::Screen::GetScreenFor(widget->GetNativeView())->
- GetWindowAtCursorScreenPoint() == widget->GetNativeWindow();
+ GetWindowUnderCursor() == widget->GetNativeWindow();
}
} // namespace views
diff --git a/ui/views/views.gyp b/ui/views/views.gyp
index 5fb9c19..7bf7666 100644
--- a/ui/views/views.gyp
+++ b/ui/views/views.gyp
@@ -275,6 +275,9 @@
'drag_controller.h',
'drag_utils.cc',
'drag_utils.h',
+ 'event_utils.h',
+ 'event_utils_aura.cc',
+ 'event_utils_win.cc',
'focus/accelerator_handler.h',
'focus/accelerator_handler_aura.cc',
'focus/accelerator_handler_win.cc',
diff --git a/ui/views/widget/desktop_aura/desktop_screen_x11.cc b/ui/views/widget/desktop_aura/desktop_screen_x11.cc
index a462da7..e581b83 100644
--- a/ui/views/widget/desktop_aura/desktop_screen_x11.cc
+++ b/ui/views/widget/desktop_aura/desktop_screen_x11.cc
@@ -38,7 +38,9 @@ class DesktopScreenX11 : public gfx::Screen {
// Overridden from gfx::Screen:
virtual bool IsDIPEnabled() OVERRIDE;
virtual gfx::Point GetCursorScreenPoint() OVERRIDE;
- virtual gfx::NativeWindow GetWindowAtCursorScreenPoint() OVERRIDE;
+ virtual gfx::NativeWindow GetWindowUnderCursor() OVERRIDE;
+ virtual gfx::NativeWindow GetWindowAtScreenPoint(const gfx::Point& point)
+ OVERRIDE;
virtual int GetNumDisplays() const OVERRIDE;
virtual std::vector<gfx::Display> GetAllDisplays() const OVERRIDE;
virtual gfx::Display GetDisplayNearestWindow(
@@ -90,12 +92,18 @@ gfx::Point DesktopScreenX11::GetCursorScreenPoint() {
return gfx::Point(root_x, root_y);
}
-gfx::NativeWindow DesktopScreenX11::GetWindowAtCursorScreenPoint() {
+gfx::NativeWindow DesktopScreenX11::GetWindowUnderCursor() {
// TODO(erg): Implement using the discussion at
// http://codereview.chromium.org/10279005/
return NULL;
}
+gfx::NativeWindow DesktopScreenX11::GetWindowAtScreenPoint(
+ const gfx::Point& point) {
+ NOTIMPLEMENTED();
+ return NULL;
+}
+
int DesktopScreenX11::GetNumDisplays() const {
// TODO(erg): Figure this out with oshima or piman because I have no clue
// about the XRandR implications here.
diff --git a/ui/views/win/hwnd_message_handler.h b/ui/views/win/hwnd_message_handler.h
index 8ae4619..80ad4aa 100644
--- a/ui/views/win/hwnd_message_handler.h
+++ b/ui/views/win/hwnd_message_handler.h
@@ -290,8 +290,8 @@ class VIEWS_EXPORT HWNDMessageHandler :
MSG_WM_CREATE(OnCreate)
MSG_WM_DESTROY(OnDestroy)
MSG_WM_DISPLAYCHANGE(OnDisplayChange)
- MSG_WM_ERASEBKGND(OnEraseBkgnd)
MSG_WM_ENTERSIZEMOVE(OnEnterSizeMove)
+ MSG_WM_ERASEBKGND(OnEraseBkgnd)
MSG_WM_EXITSIZEMOVE(OnExitSizeMove)
MSG_WM_GETMINMAXINFO(OnGetMinMaxInfo)
MSG_WM_INITMENU(OnInitMenu)
@@ -311,8 +311,8 @@ class VIEWS_EXPORT HWNDMessageHandler :
MSG_WM_SIZE(OnSize)
MSG_WM_SYSCOMMAND(OnSysCommand)
MSG_WM_THEMECHANGED(OnThemeChanged)
- MSG_WM_WINDOWPOSCHANGING(OnWindowPosChanging)
MSG_WM_WINDOWPOSCHANGED(OnWindowPosChanged)
+ MSG_WM_WINDOWPOSCHANGING(OnWindowPosChanging)
END_MSG_MAP()
// Message Handlers.