summaryrefslogtreecommitdiffstats
path: root/views
diff options
context:
space:
mode:
authormsw@chromium.org <msw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-07 21:23:37 +0000
committermsw@chromium.org <msw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-07 21:23:37 +0000
commit8e99bae69800b5e977667118629e64a1a37e2d9b (patch)
tree7af1942f0d83cf4d51867b78041f066758341fc3 /views
parent4fe438755445396d604cc75ac3f6ef8d3a17f156 (diff)
downloadchromium_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.cc13
-rw-r--r--views/bubble/bubble_delegate.h15
-rw-r--r--views/widget/native_widget_win.cc31
-rw-r--r--views/widget/root_view.cc3
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(