Index: ash/shell.cc |
diff --git a/ash/shell.cc b/ash/shell.cc |
index d246e6ce53d8ae98c3415b3037651b4bd1184d38..d130324d89b365acb7e281ea4cacdbbf844b5dc6 100644 |
--- a/ash/shell.cc |
+++ b/ash/shell.cc |
@@ -481,6 +481,9 @@ class DummySystemTrayDelegate : public SystemTrayDelegate { |
virtual void ChangeProxySettings() OVERRIDE { |
} |
+ virtual void OnTrayDestroyed() OVERRIDE { |
+ } |
+ |
bool muted_; |
bool wifi_enabled_; |
bool cellular_enabled_; |
@@ -530,65 +533,15 @@ Shell::Shell(ShellDelegate* delegate) |
delegate_(delegate), |
shelf_(NULL), |
root_window_layout_(NULL), |
- status_widget_(NULL) { |
+ status_widget_(NULL), |
+ shutdown_(false) { |
gfx::Screen::SetInstance(screen_); |
ui_controls::InstallUIControlsAura(CreateUIControlsAura(root_window_.get())); |
} |
Shell::~Shell() { |
- RemoveRootWindowEventFilter(key_rewriter_filter_.get()); |
- RemoveRootWindowEventFilter(partial_screenshot_filter_.get()); |
- RemoveRootWindowEventFilter(input_method_filter_.get()); |
- RemoveRootWindowEventFilter(window_modality_controller_.get()); |
- RemoveRootWindowEventFilter(system_gesture_filter_.get()); |
-#if !defined(OS_MACOSX) |
- RemoveRootWindowEventFilter(accelerator_filter_.get()); |
-#endif |
- |
- // Close background widget now so that the focus manager of the |
- // widget gets deleted in the final message loop run. |
- root_window_layout_->SetBackgroundWidget(NULL); |
- |
- // TooltipController is deleted with the Shell so removing its references. |
- RemoveRootWindowEventFilter(tooltip_controller_.get()); |
- aura::client::SetTooltipClient(GetRootWindow(), NULL); |
- |
- // Make sure we delete WorkspaceController before launcher is |
- // deleted as it has a reference to launcher model. |
- workspace_controller_.reset(); |
- |
- // The system tray needs to be reset before all the windows are destroyed. |
- tray_.reset(); |
- |
- // Desroy secondary monitor's widgets before all the windows are destroyed. |
- monitor_controller_.reset(); |
- |
- // Delete containers now so that child windows does not access |
- // observers when they are destructed. |
- aura::RootWindow* root_window = GetRootWindow(); |
- while (!root_window->children().empty()) { |
- aura::Window* child = root_window->children()[0]; |
- delete child; |
- } |
- |
- // These need a valid Shell instance to clean up properly, so explicitly |
- // delete them before invalidating the instance. |
- // Alphabetical. |
- activation_controller_.reset(); |
- drag_drop_controller_.reset(); |
- resize_shadow_controller_.reset(); |
- shadow_controller_.reset(); |
- window_cycle_controller_.reset(); |
- event_client_.reset(); |
- monitor_controller_.reset(); |
- |
- // Launcher widget has a InputMethodBridge that references to |
- // input_method_filter_'s input_method_. So explicitly release launcher_ |
- // before input_method_filter_. And this needs to be after we delete all |
- // containers in case there are still live browser windows which access |
- // LauncherModel during close. |
- launcher_.reset(); |
- |
+ if (!shutdown_) |
+ Shutdown(); |
DCHECK(instance_ == this); |
instance_ = NULL; |
} |
@@ -626,6 +579,7 @@ aura::RootWindow* Shell::GetRootWindow() { |
} |
void Shell::Init() { |
+ DCHECK(!shutdown_); |
aura::RootWindow* root_window = GetRootWindow(); |
root_filter_ = new internal::RootWindowEventFilter(root_window); |
#if !defined(OS_MACOSX) |
@@ -786,6 +740,66 @@ const aura::Window* Shell::GetContainer(int container_id) const { |
return GetRootWindow()->GetChildById(container_id); |
} |
+void Shell::Shutdown() { |
+ DCHECK(!shutdown_); |
+ shutdown_ = true; |
+ |
+ RemoveRootWindowEventFilter(key_rewriter_filter_.get()); |
+ RemoveRootWindowEventFilter(partial_screenshot_filter_.get()); |
+ RemoveRootWindowEventFilter(input_method_filter_.get()); |
+ RemoveRootWindowEventFilter(window_modality_controller_.get()); |
+ RemoveRootWindowEventFilter(system_gesture_filter_.get()); |
+#if !defined(OS_MACOSX) |
+ RemoveRootWindowEventFilter(accelerator_filter_.get()); |
+#endif |
+ |
+ // Close background widget now so that the focus manager of the |
+ // widget gets deleted in the final message loop run. |
+ root_window_layout_->SetBackgroundWidget(NULL); |
+ |
+ // TooltipController is deleted with the Shell so removing its references. |
+ RemoveRootWindowEventFilter(tooltip_controller_.get()); |
+ aura::client::SetTooltipClient(GetRootWindow(), NULL); |
+ |
+ // Make sure we delete WorkspaceController before launcher is |
+ // deleted as it has a reference to launcher model. |
+ workspace_controller_.reset(); |
+ |
+ // The system tray needs to be reset before all the windows are destroyed. |
+ tray_.reset(); |
+ tray_delegate_->OnTrayDestroyed(); |
+ |
+ // Desroy secondary monitor's widgets before all the windows are destroyed. |
+ monitor_controller_.reset(); |
+ |
+ // Delete containers now so that child windows does not access |
+ // observers when they are destructed. |
+ aura::RootWindow* root_window = GetRootWindow(); |
+ while (!root_window->children().empty()) { |
+ aura::Window* child = root_window->children()[0]; |
+ delete child; |
+ } |
+ |
+ // These need a valid Shell instance to clean up properly, so explicitly |
+ // delete them before invalidating the instance. |
+ // Alphabetical. |
+ activation_controller_.reset(); |
+ drag_drop_controller_.reset(); |
+ resize_shadow_controller_.reset(); |
+ shadow_controller_.reset(); |
+ window_cycle_controller_.reset(); |
+ event_client_.reset(); |
+ monitor_controller_.reset(); |
+ tooltip_controller_.reset(); |
+ |
+ // Launcher widget has a InputMethodBridge that references to |
+ // input_method_filter_'s input_method_. So explicitly release launcher_ |
+ // before input_method_filter_. And this needs to be after we delete all |
+ // containers in case there are still live browser windows which access |
+ // LauncherModel during close. |
+ launcher_.reset(); |
+} |
+ |
void Shell::AddRootWindowEventFilter(aura::EventFilter* filter) { |
static_cast<internal::RootWindowEventFilter*>( |
GetRootWindow()->event_filter())->AddFilter(filter); |