Index: ui/views/widget/widget.cc |
diff --git a/ui/views/widget/widget.cc b/ui/views/widget/widget.cc |
index 394715dac9046319cee0b6f7368d426c78820ac4..f0cd1db60d329aff22f59b063f3468767b032112 100644 |
--- a/ui/views/widget/widget.cc |
+++ b/ui/views/widget/widget.cc |
@@ -61,6 +61,48 @@ NativeWidget* CreateNativeWidget(NativeWidget* native_widget, |
return native_widget; |
} |
+class PostMousePressedProcessor : public WidgetObserver { |
sky
2013/03/21 22:17:48
How about declaring this as an inner class (you ca
varunjain
2013/03/21 22:47:14
Done.
|
+ public: |
+ explicit PostMousePressedProcessor(views::Widget* owner) : owner_(owner) { |
+ owner_->AddObserver(this); |
+ } |
+ |
+ virtual ~PostMousePressedProcessor() { |
+ if (owner_) { |
+ owner_->RemoveObserver(this); |
+ owner_ = NULL; |
+ } |
+ } |
+ |
+ void DoPostMousePressedProcessing() { |
+ // Make sure we're still visible before we attempt capture as the mouse |
+ // press processing may have made the window hide (as happens with menus). |
+ if (!owner_ || !owner_->IsVisible()) |
+ return; |
+ |
+ owner_->set_is_mouse_button_pressed(true); |
+ |
+ // OnNativeWidgetDestroying also notifies all |
+ // WidgetObservers::OnWidgetDestroying. So we can be sure that if |owner_| |
+ // is non-NULL, |owner_->native_widget_| will also be non-NULL. |
+ if (!owner_->native_widget_private()->HasCapture()) |
+ owner_->native_widget_private()->SetCapture(); |
+ } |
+ |
+ // Overridden from WidgetObserver. |
+ virtual void OnWidgetDestroying(Widget* widget) OVERRIDE { |
+ if (owner_) { |
sky
2013/03/21 22:17:48
Consolidate this and 71-74.
varunjain
2013/03/21 22:47:14
Done.
|
+ owner_->RemoveObserver(this); |
+ owner_ = NULL; |
+ } |
+ } |
+ |
+ private: |
+ views::Widget* owner_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(PostMousePressedProcessor); |
+}; |
+ |
} // namespace |
// This class is used to keep track of the event a Widget is processing, and |
@@ -1143,17 +1185,18 @@ void Widget::OnMouseEvent(ui::MouseEvent* event) { |
ScopedEvent scoped(this, *event); |
View* root_view = GetRootView(); |
switch (event->type()) { |
- case ui::ET_MOUSE_PRESSED: |
+ case ui::ET_MOUSE_PRESSED: { |
last_mouse_event_was_move_ = false; |
- // Make sure we're still visible before we attempt capture as the mouse |
- // press processing may have made the window hide (as happens with menus). |
- if (root_view && root_view->OnMousePressed(*event) && IsVisible()) { |
- is_mouse_button_pressed_ = true; |
- if (!native_widget_->HasCapture()) |
- native_widget_->SetCapture(); |
+ |
+ // We may get deleted by the time we return from OnMousePressed. So we |
+ // use an observer to do capture after OnMousePressed in a safe way. |
+ PostMousePressedProcessor post_mouse_pressed_processor(this); |
+ if (root_view && root_view->OnMousePressed(*event)) { |
+ post_mouse_pressed_processor.DoPostMousePressedProcessing(); |
event->SetHandled(); |
} |
return; |
+ } |
case ui::ET_MOUSE_RELEASED: |
last_mouse_event_was_move_ = false; |
is_mouse_button_pressed_ = false; |