Chromium Code Reviews| 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; |