summaryrefslogtreecommitdiffstats
path: root/ui/views/widget
diff options
context:
space:
mode:
authorsky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-22 07:30:30 +0000
committersky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-22 07:30:30 +0000
commit425969e28b738207ec204a057f294345ea5560de (patch)
tree53ac4d874b1d24d833b46af1403fbf4b2ba2a74c /ui/views/widget
parentbd1dce86395428a44c830a33e11eefc0519fbfad (diff)
downloadchromium_src-425969e28b738207ec204a057f294345ea5560de.zip
chromium_src-425969e28b738207ec204a057f294345ea5560de.tar.gz
chromium_src-425969e28b738207ec204a057f294345ea5560de.tar.bz2
Makes aura NativeWidget implementations no-op if NativeView destroyed.
Many win32 functions silently do nothing if passed an invalid HWND, which is why we haven't had to worry about this with NativeWidgetWin. I'm including a test that exercises the interesting public methods of Widget. BUG=275767 TEST=covered by tests R=ananta@chromium.org Review URL: https://chromiumcodereview.appspot.com/22880031 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@218929 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/views/widget')
-rw-r--r--ui/views/widget/desktop_aura/desktop_native_widget_aura.cc119
-rw-r--r--ui/views/widget/desktop_aura/desktop_native_widget_aura.h4
-rw-r--r--ui/views/widget/native_widget_aura.cc116
-rw-r--r--ui/views/widget/native_widget_aura.h3
-rw-r--r--ui/views/widget/widget_unittest.cc93
5 files changed, 265 insertions, 70 deletions
diff --git a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
index 476f567..3dcf931 100644
--- a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
+++ b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
@@ -315,15 +315,16 @@ Widget* DesktopNativeWidgetAura::GetTopLevelWidget() {
}
const ui::Compositor* DesktopNativeWidgetAura::GetCompositor() const {
- return window_->layer()->GetCompositor();
+ return window_ ? window_->layer()->GetCompositor() : NULL;
}
ui::Compositor* DesktopNativeWidgetAura::GetCompositor() {
- return window_->layer()->GetCompositor();
+ return const_cast<ui::Compositor*>(
+ const_cast<const DesktopNativeWidgetAura*>(this)->GetCompositor());
}
ui::Layer* DesktopNativeWidgetAura::GetLayer() {
- return window_->layer();
+ return window_ ? window_->layer() : NULL;
}
void DesktopNativeWidgetAura::ReorderNativeViews() {
@@ -335,11 +336,12 @@ void DesktopNativeWidgetAura::ViewRemoved(View* view) {
void DesktopNativeWidgetAura::SetNativeWindowProperty(const char* name,
void* value) {
- window_->SetNativeWindowProperty(name, value);
+ if (window_)
+ window_->SetNativeWindowProperty(name, value);
}
void* DesktopNativeWidgetAura::GetNativeWindowProperty(const char* name) const {
- return window_->GetNativeWindowProperty(name);
+ return window_ ? window_->GetNativeWindowProperty(name) : NULL;
}
TooltipManager* DesktopNativeWidgetAura::GetTooltipManager() const {
@@ -347,6 +349,9 @@ TooltipManager* DesktopNativeWidgetAura::GetTooltipManager() const {
}
void DesktopNativeWidgetAura::SetCapture() {
+ if (!window_)
+ return;
+
window_->SetCapture();
// aura::Window doesn't implicitly update capture on the RootWindowHost, so
// we have to do that manually.
@@ -355,6 +360,9 @@ void DesktopNativeWidgetAura::SetCapture() {
}
void DesktopNativeWidgetAura::ReleaseCapture() {
+ if (!window_)
+ return;
+
window_->ReleaseCapture();
// aura::Window doesn't implicitly update capture on the RootWindowHost, so
// we have to do that manually.
@@ -363,7 +371,8 @@ void DesktopNativeWidgetAura::ReleaseCapture() {
}
bool DesktopNativeWidgetAura::HasCapture() const {
- return window_->HasCapture() && desktop_root_window_host_->HasCapture();
+ return window_ && window_->HasCapture() &&
+ desktop_root_window_host_->HasCapture();
}
InputMethod* DesktopNativeWidgetAura::CreateInputMethod() {
@@ -377,22 +386,26 @@ internal::InputMethodDelegate*
}
void DesktopNativeWidgetAura::CenterWindow(const gfx::Size& size) {
- desktop_root_window_host_->CenterWindow(size);
+ if (window_)
+ desktop_root_window_host_->CenterWindow(size);
}
void DesktopNativeWidgetAura::GetWindowPlacement(
gfx::Rect* bounds,
ui::WindowShowState* maximized) const {
- desktop_root_window_host_->GetWindowPlacement(bounds, maximized);
+ if (window_)
+ desktop_root_window_host_->GetWindowPlacement(bounds, maximized);
}
void DesktopNativeWidgetAura::SetWindowTitle(const string16& title) {
- desktop_root_window_host_->SetWindowTitle(title);
+ if (window_)
+ desktop_root_window_host_->SetWindowTitle(title);
}
void DesktopNativeWidgetAura::SetWindowIcons(const gfx::ImageSkia& window_icon,
const gfx::ImageSkia& app_icon) {
- desktop_root_window_host_->SetWindowIcons(window_icon, app_icon);
+ if (window_)
+ desktop_root_window_host_->SetWindowIcons(window_icon, app_icon);
}
void DesktopNativeWidgetAura::InitModalType(ui::ModalType modal_type) {
@@ -403,18 +416,23 @@ void DesktopNativeWidgetAura::InitModalType(ui::ModalType modal_type) {
}
gfx::Rect DesktopNativeWidgetAura::GetWindowBoundsInScreen() const {
- return desktop_root_window_host_->GetWindowBoundsInScreen();
+ return window_ ? desktop_root_window_host_->GetWindowBoundsInScreen() :
+ gfx::Rect();
}
gfx::Rect DesktopNativeWidgetAura::GetClientAreaBoundsInScreen() const {
- return desktop_root_window_host_->GetClientAreaBoundsInScreen();
+ return window_ ? desktop_root_window_host_->GetClientAreaBoundsInScreen() :
+ gfx::Rect();
}
gfx::Rect DesktopNativeWidgetAura::GetRestoredBounds() const {
- return desktop_root_window_host_->GetRestoredBounds();
+ return window_ ? desktop_root_window_host_->GetRestoredBounds() : gfx::Rect();
}
void DesktopNativeWidgetAura::SetBounds(const gfx::Rect& bounds) {
+ if (!window_)
+ return;
+
float scale = 1;
aura::RootWindow* root = root_window_.get();
if (root) {
@@ -428,7 +446,8 @@ void DesktopNativeWidgetAura::SetBounds(const gfx::Rect& bounds) {
}
void DesktopNativeWidgetAura::SetSize(const gfx::Size& size) {
- desktop_root_window_host_->SetSize(size);
+ if (window_)
+ desktop_root_window_host_->SetSize(size);
}
void DesktopNativeWidgetAura::StackAbove(gfx::NativeView native_view) {
@@ -441,98 +460,117 @@ void DesktopNativeWidgetAura::StackBelow(gfx::NativeView native_view) {
}
void DesktopNativeWidgetAura::SetShape(gfx::NativeRegion shape) {
- desktop_root_window_host_->SetShape(shape);
+ if (window_)
+ desktop_root_window_host_->SetShape(shape);
}
void DesktopNativeWidgetAura::Close() {
+ if (!window_)
+ return;
desktop_root_window_host_->Close();
- if (window_)
- window_->SuppressPaint();
+ window_->SuppressPaint();
}
void DesktopNativeWidgetAura::CloseNow() {
- desktop_root_window_host_->CloseNow();
+ if (window_)
+ desktop_root_window_host_->CloseNow();
}
void DesktopNativeWidgetAura::Show() {
+ if (!window_)
+ return;
desktop_root_window_host_->AsRootWindowHost()->Show();
window_->Show();
}
void DesktopNativeWidgetAura::Hide() {
+ if (!window_)
+ return;
desktop_root_window_host_->AsRootWindowHost()->Hide();
- if (window_)
- window_->Hide();
+ window_->Hide();
}
void DesktopNativeWidgetAura::ShowMaximizedWithBounds(
const gfx::Rect& restored_bounds) {
+ if (!window_)
+ return;
desktop_root_window_host_->ShowMaximizedWithBounds(restored_bounds);
window_->Show();
}
void DesktopNativeWidgetAura::ShowWithWindowState(ui::WindowShowState state) {
+ if (!window_)
+ return;
desktop_root_window_host_->ShowWindowWithState(state);
window_->Show();
}
bool DesktopNativeWidgetAura::IsVisible() const {
- return desktop_root_window_host_->IsVisible();
+ return window_ && desktop_root_window_host_->IsVisible();
}
void DesktopNativeWidgetAura::Activate() {
- desktop_root_window_host_->Activate();
+ if (window_)
+ desktop_root_window_host_->Activate();
}
void DesktopNativeWidgetAura::Deactivate() {
- desktop_root_window_host_->Deactivate();
+ if (window_)
+ desktop_root_window_host_->Deactivate();
}
bool DesktopNativeWidgetAura::IsActive() const {
- return desktop_root_window_host_->IsActive();
+ return window_ && desktop_root_window_host_->IsActive();
}
void DesktopNativeWidgetAura::SetAlwaysOnTop(bool always_on_top) {
- desktop_root_window_host_->SetAlwaysOnTop(always_on_top);
+ if (window_)
+ desktop_root_window_host_->SetAlwaysOnTop(always_on_top);
}
void DesktopNativeWidgetAura::Maximize() {
- desktop_root_window_host_->Maximize();
+ if (window_)
+ desktop_root_window_host_->Maximize();
}
void DesktopNativeWidgetAura::Minimize() {
- desktop_root_window_host_->Minimize();
+ if (window_)
+ desktop_root_window_host_->Minimize();
}
bool DesktopNativeWidgetAura::IsMaximized() const {
- return desktop_root_window_host_->IsMaximized();
+ return window_ && desktop_root_window_host_->IsMaximized();
}
bool DesktopNativeWidgetAura::IsMinimized() const {
- return desktop_root_window_host_->IsMinimized();
+ return window_ && desktop_root_window_host_->IsMinimized();
}
void DesktopNativeWidgetAura::Restore() {
- desktop_root_window_host_->Restore();
+ if (window_)
+ desktop_root_window_host_->Restore();
}
void DesktopNativeWidgetAura::SetFullscreen(bool fullscreen) {
- desktop_root_window_host_->SetFullscreen(fullscreen);
+ if (window_)
+ desktop_root_window_host_->SetFullscreen(fullscreen);
}
bool DesktopNativeWidgetAura::IsFullscreen() const {
- return desktop_root_window_host_->IsFullscreen();
+ return window_ && desktop_root_window_host_->IsFullscreen();
}
void DesktopNativeWidgetAura::SetOpacity(unsigned char opacity) {
- desktop_root_window_host_->SetOpacity(opacity);
+ if (window_)
+ desktop_root_window_host_->SetOpacity(opacity);
}
void DesktopNativeWidgetAura::SetUseDragFrame(bool use_drag_frame) {
}
void DesktopNativeWidgetAura::FlashFrame(bool flash_frame) {
- desktop_root_window_host_->FlashFrame(flash_frame);
+ if (window_)
+ desktop_root_window_host_->FlashFrame(flash_frame);
}
void DesktopNativeWidgetAura::RunShellDrag(
@@ -558,6 +596,8 @@ void DesktopNativeWidgetAura::SetCursor(gfx::NativeCursor cursor) {
}
bool DesktopNativeWidgetAura::IsMouseEventsEnabled() const {
+ if (!window_)
+ return false;
aura::client::CursorClient* cursor_client =
aura::client::GetCursorClient(window_->GetRootWindow());
return cursor_client ? cursor_client->IsMouseEventsEnabled() : true;
@@ -577,6 +617,9 @@ gfx::Rect DesktopNativeWidgetAura::GetWorkAreaBoundsInScreen() const {
}
void DesktopNativeWidgetAura::SetInactiveRenderingDisabled(bool value) {
+ if (!window_)
+ return;
+
if (!value) {
active_window_observer_.reset();
} else {
@@ -588,16 +631,20 @@ void DesktopNativeWidgetAura::SetInactiveRenderingDisabled(bool value) {
Widget::MoveLoopResult DesktopNativeWidgetAura::RunMoveLoop(
const gfx::Vector2d& drag_offset,
Widget::MoveLoopSource source) {
+ if (!window_)
+ return Widget::MOVE_LOOP_CANCELED;
return desktop_root_window_host_->RunMoveLoop(drag_offset, source);
}
void DesktopNativeWidgetAura::EndMoveLoop() {
- desktop_root_window_host_->EndMoveLoop();
+ if (window_)
+ desktop_root_window_host_->EndMoveLoop();
}
void DesktopNativeWidgetAura::SetVisibilityChangedAnimationsEnabled(
bool value) {
- desktop_root_window_host_->SetVisibilityChangedAnimationsEnabled(value);
+ if (window_)
+ desktop_root_window_host_->SetVisibilityChangedAnimationsEnabled(value);
}
ui::NativeTheme* DesktopNativeWidgetAura::GetNativeTheme() const {
diff --git a/ui/views/widget/desktop_aura/desktop_native_widget_aura.h b/ui/views/widget/desktop_aura/desktop_native_widget_aura.h
index b98e1cc..b497440 100644
--- a/ui/views/widget/desktop_aura/desktop_native_widget_aura.h
+++ b/ui/views/widget/desktop_aura/desktop_native_widget_aura.h
@@ -224,7 +224,11 @@ class VIEWS_EXPORT DesktopNativeWidgetAura
// Ownership passed to RootWindow on Init.
DesktopRootWindowHost* desktop_root_window_host_;
+
+ // The content of |root_window_|. WARNING: this may be NULL if deleted out
+ // from under us.
aura::Window* window_;
+
internal::NativeWidgetDelegate* native_widget_delegate_;
scoped_ptr<aura::client::StackingClient> stacking_client_;
diff --git a/ui/views/widget/native_widget_aura.cc b/ui/views/widget/native_widget_aura.cc
index 8c9ad02..8a80068 100644
--- a/ui/views/widget/native_widget_aura.cc
+++ b/ui/views/widget/native_widget_aura.cc
@@ -222,15 +222,15 @@ Widget* NativeWidgetAura::GetTopLevelWidget() {
}
const ui::Compositor* NativeWidgetAura::GetCompositor() const {
- return window_->layer()->GetCompositor();
+ return window_ ? window_->layer()->GetCompositor() : NULL;
}
ui::Compositor* NativeWidgetAura::GetCompositor() {
- return window_->layer()->GetCompositor();
+ return window_ ? window_->layer()->GetCompositor() : NULL;
}
ui::Layer* NativeWidgetAura::GetLayer() {
- return window_->layer();
+ return window_ ? window_->layer() : NULL;
}
void NativeWidgetAura::ReorderNativeViews() {
@@ -256,18 +256,22 @@ TooltipManager* NativeWidgetAura::GetTooltipManager() const {
}
void NativeWidgetAura::SetCapture() {
- window_->SetCapture();
+ if (window_)
+ window_->SetCapture();
}
void NativeWidgetAura::ReleaseCapture() {
- window_->ReleaseCapture();
+ if (window_)
+ window_->ReleaseCapture();
}
bool NativeWidgetAura::HasCapture() const {
- return window_->HasCapture();
+ return window_ && window_->HasCapture();
}
InputMethod* NativeWidgetAura::CreateInputMethod() {
+ if (!window_)
+ return NULL;
aura::RootWindow* root_window = window_->GetRootWindow();
ui::InputMethod* host =
root_window->GetProperty(aura::client::kRootWindowInputMethodKey);
@@ -279,6 +283,9 @@ internal::InputMethodDelegate* NativeWidgetAura::GetInputMethodDelegate() {
}
void NativeWidgetAura::CenterWindow(const gfx::Size& size) {
+ if (!window_)
+ return;
+
gfx::Rect parent_bounds(window_->parent()->GetBoundsInRootWindow());
// When centering window, we take the intersection of the host and
// the parent. We assume the root window represents the visible
@@ -330,11 +337,13 @@ void NativeWidgetAura::GetWindowPlacement(
ui::WindowShowState* show_state) const {
// The interface specifies returning restored bounds, not current bounds.
*bounds = GetRestoredBounds();
- *show_state = window_->GetProperty(aura::client::kShowStateKey);
+ *show_state = window_ ? window_->GetProperty(aura::client::kShowStateKey) :
+ ui::SHOW_STATE_DEFAULT;
}
void NativeWidgetAura::SetWindowTitle(const string16& title) {
- window_->set_title(title);
+ if (window_)
+ window_->set_title(title);
}
void NativeWidgetAura::SetWindowIcons(const gfx::ImageSkia& window_icon,
@@ -348,16 +357,19 @@ void NativeWidgetAura::InitModalType(ui::ModalType modal_type) {
}
gfx::Rect NativeWidgetAura::GetWindowBoundsInScreen() const {
- return window_->GetBoundsInScreen();
+ return window_ ? window_->GetBoundsInScreen() : gfx::Rect();
}
gfx::Rect NativeWidgetAura::GetClientAreaBoundsInScreen() const {
// View-to-screen coordinate system transformations depend on this returning
// the full window bounds, for example View::ConvertPointToScreen().
- return window_->GetBoundsInScreen();
+ return window_ ? window_->GetBoundsInScreen() : gfx::Rect();
}
gfx::Rect NativeWidgetAura::GetRestoredBounds() const {
+ if (!window_)
+ return gfx::Rect();
+
// Restored bounds should only be relevant if the window is minimized or
// maximized. However, in some places the code expects GetRestoredBounds()
// to return the current window bounds if the window is not in either state.
@@ -372,6 +384,9 @@ gfx::Rect NativeWidgetAura::GetRestoredBounds() const {
}
void NativeWidgetAura::SetBounds(const gfx::Rect& bounds) {
+ if (!window_)
+ return;
+
aura::RootWindow* root = window_->GetRootWindow();
if (root) {
aura::client::ScreenPositionClient* screen_position_client =
@@ -387,20 +402,24 @@ void NativeWidgetAura::SetBounds(const gfx::Rect& bounds) {
}
void NativeWidgetAura::SetSize(const gfx::Size& size) {
- window_->SetBounds(gfx::Rect(window_->bounds().origin(), size));
+ if (window_)
+ window_->SetBounds(gfx::Rect(window_->bounds().origin(), size));
}
void NativeWidgetAura::StackAbove(gfx::NativeView native_view) {
- if (window_->parent() && window_->parent() == native_view->parent())
+ if (window_ && window_->parent() &&
+ window_->parent() == native_view->parent())
window_->parent()->StackChildAbove(window_, native_view);
}
void NativeWidgetAura::StackAtTop() {
- window_->parent()->StackChildAtTop(window_);
+ if (window_)
+ window_->parent()->StackChildAtTop(window_);
}
void NativeWidgetAura::StackBelow(gfx::NativeView native_view) {
- if (window_->parent() && window_->parent() == native_view->parent())
+ if (window_ && window_->parent() &&
+ window_->parent() == native_view->parent())
window_->parent()->StackChildBelow(window_, native_view);
}
@@ -438,7 +457,8 @@ void NativeWidgetAura::Show() {
}
void NativeWidgetAura::Hide() {
- window_->Hide();
+ if (window_)
+ window_->Hide();
}
void NativeWidgetAura::ShowMaximizedWithBounds(
@@ -448,6 +468,9 @@ void NativeWidgetAura::ShowMaximizedWithBounds(
}
void NativeWidgetAura::ShowWithWindowState(ui::WindowShowState state) {
+ if (!window_)
+ return;
+
if (state == ui::SHOW_STATE_MAXIMIZED || state == ui::SHOW_STATE_FULLSCREEN)
window_->SetProperty(aura::client::kShowStateKey, state);
window_->Show();
@@ -466,10 +489,13 @@ void NativeWidgetAura::ShowWithWindowState(ui::WindowShowState state) {
}
bool NativeWidgetAura::IsVisible() const {
- return window_->IsVisible();
+ return window_ && window_->IsVisible();
}
void NativeWidgetAura::Activate() {
+ if (!window_)
+ return;
+
// We don't necessarily have a root window yet. This can happen with
// constrained windows.
if (window_->GetRootWindow()) {
@@ -481,43 +507,50 @@ void NativeWidgetAura::Activate() {
}
void NativeWidgetAura::Deactivate() {
+ if (!window_)
+ return;
aura::client::GetActivationClient(window_->GetRootWindow())->DeactivateWindow(
window_);
}
bool NativeWidgetAura::IsActive() const {
- return aura::client::GetActivationClient(window_->GetRootWindow())->
- GetActiveWindow() == window_;
+ return window_ &&
+ aura::client::GetActivationClient(window_->GetRootWindow())->
+ GetActiveWindow() == window_;
}
void NativeWidgetAura::SetAlwaysOnTop(bool on_top) {
- window_->SetProperty(aura::client::kAlwaysOnTopKey, on_top);
+ if (window_)
+ window_->SetProperty(aura::client::kAlwaysOnTopKey, on_top);
}
void NativeWidgetAura::Maximize() {
- window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
+ if (window_)
+ window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
}
void NativeWidgetAura::Minimize() {
- window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
+ if (window_)
+ window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
}
bool NativeWidgetAura::IsMaximized() const {
- return window_->GetProperty(aura::client::kShowStateKey) ==
+ return window_ && window_->GetProperty(aura::client::kShowStateKey) ==
ui::SHOW_STATE_MAXIMIZED;
}
bool NativeWidgetAura::IsMinimized() const {
- return window_->GetProperty(aura::client::kShowStateKey) ==
+ return window_ && window_->GetProperty(aura::client::kShowStateKey) ==
ui::SHOW_STATE_MINIMIZED;
}
void NativeWidgetAura::Restore() {
- window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
+ if (window_)
+ window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
}
void NativeWidgetAura::SetFullscreen(bool fullscreen) {
- if (IsFullscreen() == fullscreen)
+ if (!window_ || IsFullscreen() == fullscreen)
return; // Nothing to do.
// Save window state before entering full screen so that it could restored
@@ -531,12 +564,13 @@ void NativeWidgetAura::SetFullscreen(bool fullscreen) {
}
bool NativeWidgetAura::IsFullscreen() const {
- return window_->GetProperty(aura::client::kShowStateKey) ==
+ return window_ && window_->GetProperty(aura::client::kShowStateKey) ==
ui::SHOW_STATE_FULLSCREEN;
}
void NativeWidgetAura::SetOpacity(unsigned char opacity) {
- window_->layer()->SetOpacity(opacity / 255.0);
+ if (window_)
+ window_->layer()->SetOpacity(opacity / 255.0);
}
void NativeWidgetAura::SetUseDragFrame(bool use_drag_frame) {
@@ -544,7 +578,8 @@ void NativeWidgetAura::SetUseDragFrame(bool use_drag_frame) {
}
void NativeWidgetAura::FlashFrame(bool flash) {
- window_->SetProperty(aura::client::kDrawAttentionKey, flash);
+ if (window_)
+ window_->SetProperty(aura::client::kDrawAttentionKey, flash);
}
void NativeWidgetAura::RunShellDrag(View* view,
@@ -552,7 +587,8 @@ void NativeWidgetAura::RunShellDrag(View* view,
const gfx::Point& location,
int operation,
ui::DragDropTypes::DragEventSource source) {
- views::RunShellDrag(window_, data, location, operation, source);
+ if (window_)
+ views::RunShellDrag(window_, data, location, operation, source);
}
void NativeWidgetAura::SchedulePaintInRect(const gfx::Rect& rect) {
@@ -569,6 +605,8 @@ void NativeWidgetAura::SetCursor(gfx::NativeCursor cursor) {
}
bool NativeWidgetAura::IsMouseEventsEnabled() const {
+ if (!window_)
+ return false;
aura::client::CursorClient* cursor_client =
aura::client::GetCursorClient(window_->GetRootWindow());
return cursor_client ? cursor_client->IsMouseEventsEnabled() : true;
@@ -581,11 +619,16 @@ void NativeWidgetAura::ClearNativeFocus() {
}
gfx::Rect NativeWidgetAura::GetWorkAreaBoundsInScreen() const {
- return gfx::Screen::GetScreenFor(GetNativeView())->
- GetDisplayNearestWindow(GetNativeView()).work_area();
+ if (!window_)
+ return gfx::Rect();
+ return gfx::Screen::GetScreenFor(window_)->
+ GetDisplayNearestWindow(window_).work_area();
}
void NativeWidgetAura::SetInactiveRenderingDisabled(bool value) {
+ if (!window_)
+ return;
+
if (!value) {
active_window_observer_.reset();
} else {
@@ -597,7 +640,7 @@ void NativeWidgetAura::SetInactiveRenderingDisabled(bool value) {
Widget::MoveLoopResult NativeWidgetAura::RunMoveLoop(
const gfx::Vector2d& drag_offset,
Widget::MoveLoopSource source) {
- if (window_->parent() &&
+ if (window_ && window_->parent() &&
aura::client::GetWindowMoveClient(window_->parent())) {
SetCapture();
aura::client::WindowMoveSource window_move_source =
@@ -614,14 +657,15 @@ Widget::MoveLoopResult NativeWidgetAura::RunMoveLoop(
}
void NativeWidgetAura::EndMoveLoop() {
- if (window_->parent() &&
+ if (window_ && window_->parent() &&
aura::client::GetWindowMoveClient(window_->parent())) {
aura::client::GetWindowMoveClient(window_->parent())->EndMoveLoop();
}
}
void NativeWidgetAura::SetVisibilityChangedAnimationsEnabled(bool value) {
- window_->SetProperty(aura::client::kAnimationsDisabledKey, !value);
+ if (window_)
+ window_->SetProperty(aura::client::kAnimationsDisabledKey, !value);
}
ui::NativeTheme* NativeWidgetAura::GetNativeTheme() const {
@@ -759,6 +803,7 @@ scoped_refptr<ui::Texture> NativeWidgetAura::CopyTexture() {
// NativeWidgetAura, ui::EventHandler implementation:
void NativeWidgetAura::OnKeyEvent(ui::KeyEvent* event) {
+ DCHECK(window_);
if (event->is_char()) {
// If a ui::InputMethod object is attached to the root window, character
// events are handled inside the object and are not passed to this function.
@@ -775,6 +820,7 @@ void NativeWidgetAura::OnKeyEvent(ui::KeyEvent* event) {
}
void NativeWidgetAura::OnMouseEvent(ui::MouseEvent* event) {
+ DCHECK(window_);
DCHECK(window_->IsVisible());
if (event->type() == ui::ET_MOUSEWHEEL) {
delegate_->OnMouseEvent(event);
@@ -792,11 +838,13 @@ void NativeWidgetAura::OnScrollEvent(ui::ScrollEvent* event) {
}
void NativeWidgetAura::OnTouchEvent(ui::TouchEvent* event) {
+ DCHECK(window_);
DCHECK(window_->IsVisible());
delegate_->OnTouchEvent(event);
}
void NativeWidgetAura::OnGestureEvent(ui::GestureEvent* event) {
+ DCHECK(window_);
DCHECK(window_->IsVisible());
delegate_->OnGestureEvent(event);
}
diff --git a/ui/views/widget/native_widget_aura.h b/ui/views/widget/native_widget_aura.h
index 57271e8..6e736a5 100644
--- a/ui/views/widget/native_widget_aura.h
+++ b/ui/views/widget/native_widget_aura.h
@@ -189,6 +189,9 @@ class VIEWS_EXPORT NativeWidgetAura
internal::NativeWidgetDelegate* delegate_;
+ // WARNING: set to NULL when destroyed. As the Widget is not necessarily
+ // destroyed along with |window_| all usage of |window_| should first verify
+ // non-NULL.
aura::Window* window_;
// See class documentation for Widget in widget.h for a note about ownership.
diff --git a/ui/views/widget/widget_unittest.cc b/ui/views/widget/widget_unittest.cc
index b9e32d6..4e195cf 100644
--- a/ui/views/widget/widget_unittest.cc
+++ b/ui/views/widget/widget_unittest.cc
@@ -941,6 +941,99 @@ TEST_F(WidgetOwnershipTest,
}
////////////////////////////////////////////////////////////////////////////////
+// Test to verify using various Widget methods doesn't crash when the underlying
+// NativeView is destroyed.
+//
+class WidgetWithDestroyedNativeViewTest : public ViewsTestBase {
+ public:
+ WidgetWithDestroyedNativeViewTest() {}
+ virtual ~WidgetWithDestroyedNativeViewTest() {}
+
+ void InvokeWidgetMethods(Widget* widget) {
+ widget->GetNativeView();
+ widget->GetNativeWindow();
+ ui::Accelerator accelerator;
+ widget->GetAccelerator(0, &accelerator);
+ widget->GetTopLevelWidget();
+ widget->GetWindowBoundsInScreen();
+ widget->GetClientAreaBoundsInScreen();
+ widget->SetBounds(gfx::Rect(0, 0, 100, 80));
+ widget->SetSize(gfx::Size(10, 11));
+ widget->SetBoundsConstrained(gfx::Rect(0, 0, 120, 140));
+ widget->SetVisibilityChangedAnimationsEnabled(false);
+ widget->StackAtTop();
+ widget->IsClosed();
+ widget->Close();
+ widget->Show();
+ widget->Hide();
+ widget->Activate();
+ widget->Deactivate();
+ widget->IsActive();
+ widget->DisableInactiveRendering();
+ widget->SetAlwaysOnTop(true);
+ widget->Maximize();
+ widget->Minimize();
+ widget->Restore();
+ widget->IsMaximized();
+ widget->IsFullscreen();
+ widget->SetOpacity(0);
+ widget->SetUseDragFrame(true);
+ widget->FlashFrame(true);
+ widget->IsVisible();
+ widget->GetThemeProvider();
+ widget->GetNativeTheme();
+ widget->GetFocusManager();
+ widget->GetInputMethod();
+ widget->SchedulePaintInRect(gfx::Rect(0, 0, 1, 2));
+ widget->IsMouseEventsEnabled();
+ widget->SetNativeWindowProperty("xx", widget);
+ widget->GetNativeWindowProperty("xx");
+ widget->GetFocusTraversable();
+ widget->GetLayer();
+ widget->ReorderNativeViews();
+ widget->SetCapture(widget->GetRootView());
+ widget->ReleaseCapture();
+ widget->HasCapture();
+ widget->TooltipTextChanged(widget->GetRootView());
+ widget->GetWorkAreaBoundsInScreen();
+ // These three crash with NativeWidgetWin, so I'm assuming we don't need
+ // them to work for the other NativeWidget impls.
+ // widget->CenterWindow(gfx::Size(50, 60));
+ // widget->GetRestoredBounds();
+ // widget->ShowInactive();
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(WidgetWithDestroyedNativeViewTest);
+};
+
+TEST_F(WidgetWithDestroyedNativeViewTest, Test) {
+ {
+ Widget widget;
+ Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
+ params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ widget.Init(params);
+ widget.Show();
+
+ widget.native_widget_private()->CloseNow();
+ InvokeWidgetMethods(&widget);
+ }
+#if defined(USE_AURA) && !defined(OS_CHROMEOS)
+ {
+ Widget widget;
+ Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
+ params.native_widget = new DesktopNativeWidgetAura(&widget);
+ params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ widget.Init(params);
+ widget.Show();
+
+ widget.native_widget_private()->CloseNow();
+ InvokeWidgetMethods(&widget);
+ }
+#endif
+}
+
+////////////////////////////////////////////////////////////////////////////////
// Widget observer tests.
//