diff options
author | msw@chromium.org <msw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-07 21:23:37 +0000 |
---|---|---|
committer | msw@chromium.org <msw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-07 21:23:37 +0000 |
commit | 8e99bae69800b5e977667118629e64a1a37e2d9b (patch) | |
tree | 7af1942f0d83cf4d51867b78041f066758341fc3 /views | |
parent | 4fe438755445396d604cc75ac3f6ef8d3a17f156 (diff) | |
download | chromium_src-8e99bae69800b5e977667118629e64a1a37e2d9b.zip chromium_src-8e99bae69800b5e977667118629e64a1a37e2d9b.tar.gz chromium_src-8e99bae69800b5e977667118629e64a1a37e2d9b.tar.bz2 |
Close new bubbles on deactivate; disable rendering Chrome inactive.
Implement WidgetFocusChangeListener, close on deactivate.
DisableInactiveRendering on the parent's top level widget.
Notify widgets without non-client views of activation changes.
To ensure bubble owners get the first click event that closes the bubble:
Stop explicitly setting the owner as the foreground window on close.
To ensure that removing this code didn't regress crbug.com/75610:
Add WS_POPUP for modal dialogs and re-enable owners on close (allowing OS activation).
Note: Showing bubbles long after CreateBubble might break DisableInactiveRendering.
BUG=97248,98312
TEST=views_examples bubbles close on deactivate, example window never appears deactivated.
Review URL: http://codereview.chromium.org/8384020
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@108912 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'views')
-rw-r--r-- | views/bubble/bubble_delegate.cc | 13 | ||||
-rw-r--r-- | views/bubble/bubble_delegate.h | 15 | ||||
-rw-r--r-- | views/widget/native_widget_win.cc | 31 | ||||
-rw-r--r-- | views/widget/root_view.cc | 3 |
4 files changed, 39 insertions, 23 deletions
diff --git a/views/bubble/bubble_delegate.cc b/views/bubble/bubble_delegate.cc index 0fb15cc..e4a0c63 100644 --- a/views/bubble/bubble_delegate.cc +++ b/views/bubble/bubble_delegate.cc @@ -75,6 +75,7 @@ Widget* CreateBorderWidget(BubbleDelegateView* bubble, Widget* parent) { BubbleDelegateView::BubbleDelegateView() : close_on_esc_(true), + close_on_deactivate_(true), allow_bubble_offscreen_(true), arrow_location_(BubbleBorder::TOP_LEFT), color_(SK_ColorWHITE), @@ -88,6 +89,7 @@ BubbleDelegateView::BubbleDelegateView( BubbleBorder::ArrowLocation arrow_location, const SkColor& color) : close_on_esc_(true), + close_on_deactivate_(true), allow_bubble_offscreen_(true), anchor_point_(anchor_point), arrow_location_(arrow_location), @@ -117,6 +119,9 @@ Widget* BubbleDelegateView::CreateBubble(BubbleDelegateView* bubble_delegate, bubble_widget->SetBounds(bubble_delegate->GetBubbleBounds()); #endif + bubble_widget->AddObserver(bubble_delegate); + if (parent_widget && parent_widget->GetTopLevelWidget()) + parent_widget->GetTopLevelWidget()->DisableInactiveRendering(); return bubble_widget; } @@ -135,6 +140,14 @@ NonClientFrameView* BubbleDelegateView::CreateNonClientFrameView() { allow_bubble_offscreen_); } +void BubbleDelegateView::OnWidgetActivationChanged(Widget* widget, + bool active) { + if (close_on_deactivate() && widget == GetWidget() && !active) { + GetWidget()->RemoveObserver(this); + GetWidget()->Close(); + } +} + gfx::Point BubbleDelegateView::GetAnchorPoint() { return anchor_point_; } diff --git a/views/bubble/bubble_delegate.h b/views/bubble/bubble_delegate.h index 28b1691..eb6df90 100644 --- a/views/bubble/bubble_delegate.h +++ b/views/bubble/bubble_delegate.h @@ -9,6 +9,7 @@ #include "base/gtest_prod_util.h" #include "ui/base/animation/animation_delegate.h" #include "views/bubble/bubble_border.h" +#include "views/widget/widget.h" #include "views/widget/widget_delegate.h" namespace ui { @@ -24,7 +25,8 @@ class BubbleFrameView; // /////////////////////////////////////////////////////////////////////////////// class VIEWS_EXPORT BubbleDelegateView : public WidgetDelegateView, - public ui::AnimationDelegate { + public ui::AnimationDelegate, + public Widget::Observer { public: BubbleDelegateView(); BubbleDelegateView(const gfx::Point& anchor_point, @@ -41,9 +43,17 @@ class VIEWS_EXPORT BubbleDelegateView : public WidgetDelegateView, virtual View* GetContentsView() OVERRIDE; virtual NonClientFrameView* CreateNonClientFrameView() OVERRIDE; + // Widget::Observer overrides: + virtual void OnWidgetActivationChanged(Widget* widget, bool active) OVERRIDE; + bool close_on_esc() const { return close_on_esc_; } void set_close_on_esc(bool close_on_esc) { close_on_esc_ = close_on_esc; } + bool close_on_deactivate() const { return close_on_deactivate_; } + void set_close_on_deactivate(bool close_on_deactivate) { + close_on_deactivate_ = close_on_deactivate; + } + bool allow_bubble_offscreen() const { return allow_bubble_offscreen_; } void set_allow_bubble_offscreen(bool allow_bubble_offscreen) { allow_bubble_offscreen_ = allow_bubble_offscreen; @@ -100,8 +110,9 @@ class VIEWS_EXPORT BubbleDelegateView : public WidgetDelegateView, // Fade animation for bubble. scoped_ptr<ui::SlideAnimation> fade_animation_; - // Should this bubble close on the escape key? + // Flags controlling bubble closure on the escape key and deactivation. bool close_on_esc_; + bool close_on_deactivate_; // Whether the bubble is allowed to be displayed offscreen, or if auto // re-positioning should be performed. diff --git a/views/widget/native_widget_win.cc b/views/widget/native_widget_win.cc index c356c12..14bc426 100644 --- a/views/widget/native_widget_win.cc +++ b/views/widget/native_widget_win.cc @@ -833,6 +833,10 @@ void NativeWidgetWin::Close() { // Let's hide ourselves right away. Hide(); + // Modal dialog windows disable their owner windows; re-enable them now so + // they can activate as foreground windows upon this window's destruction. + RestoreEnabledIfNecessary(); + if (!close_widget_factory_.HasWeakPtrs()) { // And we delay the close so that if we are called from an ATL callback, // we don't destroy the window before the callback returned (as the caller @@ -843,22 +847,6 @@ void NativeWidgetWin::Close() { base::Bind(&NativeWidgetWin::CloseNow, close_widget_factory_.GetWeakPtr())); } - - // If the user activates another app after opening us, then comes back and - // closes us, we want our owner to gain activation. But only if the owner - // is visible. If we don't manually force that here, the other app will - // regain activation instead. - // It's tempting to think that this could be done from OnDestroy, but by then - // it's too late - GetForegroundWindow() will return the window that Windows - // has decided to re-activate for us instead of this dialog. It's also - // tempting to think about removing the foreground window check entirely, but - // it's necessary to this code path from being triggered when an inactive - // window is closed. - HWND owner = ::GetWindow(GetNativeView(), GW_OWNER); - if (owner && GetNativeView() == GetForegroundWindow() && - IsWindowVisible(owner)) { - SetForegroundWindow(owner); - } } void NativeWidgetWin::CloseNow() { @@ -1315,7 +1303,6 @@ LRESULT NativeWidgetWin::OnCreate(CREATESTRUCT* create_struct) { } void NativeWidgetWin::OnDestroy() { - RestoreEnabledIfNecessary(); delegate_->OnNativeWidgetDestroying(); if (drop_target_.get()) { RevokeDragDrop(hwnd()); @@ -1605,6 +1592,9 @@ void NativeWidgetWin::OnMoving(UINT param, const LPRECT new_bounds) { } LRESULT NativeWidgetWin::OnNCActivate(BOOL active) { + if (delegate_->CanActivate()) + delegate_->OnNativeWidgetActivationChanged(!!active); + if (!GetWidget()->non_client_view()) { SetMsgHandled(FALSE); return 0; @@ -1613,8 +1603,6 @@ LRESULT NativeWidgetWin::OnNCActivate(BOOL active) { if (!delegate_->CanActivate()) return TRUE; - delegate_->OnNativeWidgetActivationChanged(!!active); - // The frame may need to redraw as a result of the activation change. // We can get WM_NCACTIVATE before we're actually visible. If we're not // visible, no need to paint. @@ -2276,6 +2264,11 @@ void NativeWidgetWin::SetInitParams(const Widget::InitParams& params) { // from the system menu, which is worse. We may need to provide our own // menu to get the close button to appear properly. // style &= ~WS_SYSMENU; + + // Set the WS_POPUP style for modal dialogs. This ensures that the owner + // window is activated on destruction. This style should not be set for + // non-modal non-top-level dialogs like constrained windows. + style |= delegate_->IsModal() ? WS_POPUP : 0; } ex_style |= delegate_->IsDialogBox() ? WS_EX_DLGMODALFRAME : 0; break; diff --git a/views/widget/root_view.cc b/views/widget/root_view.cc index 878e236..a9cb2b3 100644 --- a/views/widget/root_view.cc +++ b/views/widget/root_view.cc @@ -200,8 +200,7 @@ bool RootView::OnMousePressed(const MouseEvent& event) { // Remove the double-click flag if the handler is different than the // one which got the first click part of the double-click. if (mouse_pressed_handler_ != last_click_handler_) - mouse_pressed_event.set_flags(e.flags() & - ~ui::EF_IS_DOUBLE_CLICK); + mouse_pressed_event.set_flags(e.flags() & ~ui::EF_IS_DOUBLE_CLICK); drag_info.Reset(); bool handled = mouse_pressed_handler_->ProcessMousePressed( |