diff options
author | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-07 01:32:50 +0000 |
---|---|---|
committer | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-07 01:32:50 +0000 |
commit | 9e40ba59d4a63f960b44f745eb5d802dbeda2e37 (patch) | |
tree | c26f9f99c0beb499380b1d7cb929bcae997756c2 /chrome | |
parent | da1e204fa55509cbb95fa215e53824b37ef54077 (diff) | |
download | chromium_src-9e40ba59d4a63f960b44f745eb5d802dbeda2e37.zip chromium_src-9e40ba59d4a63f960b44f745eb5d802dbeda2e37.tar.gz chromium_src-9e40ba59d4a63f960b44f745eb5d802dbeda2e37.tar.bz2 |
Remove all traces of NotificationService from views.
Specifically, notifies the FocusManager and ViewStorage directly when the view hierarchy is adjusted rather than using notifications. This change is based on the assumption that there is one focus manager per toplevel window. I think I remember you saying this before Jay.
Removes the "window open/close" notifications since they aren't used at the Views level... the close notification is already sent manually by the BrowserView for automation so that continues to work.
Moves the HWNDNotificationSource to common, since it's used by BrowserView.
Rejiggers the BrowserList/Window to call a function implemented in the ViewsFE that handles closing non-app windows when the last browser window is closed.
http://crbug.com/11387
Committed: http://src.chromium.org/viewvc/chrome?view=rev&revision=15468
Review URL: http://codereview.chromium.org/113016
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@15489 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/automation/automation_window_tracker.h | 2 | ||||
-rw-r--r-- | chrome/browser/browser_list.cc | 8 | ||||
-rw-r--r-- | chrome/browser/browser_list.h | 3 | ||||
-rw-r--r-- | chrome/browser/views/frame/browser_view.cc | 7 | ||||
-rw-r--r-- | chrome/common/common.vcproj | 4 | ||||
-rw-r--r-- | chrome/common/hwnd_notification_source.h (renamed from chrome/views/widget/hwnd_notification_source.h) | 6 | ||||
-rw-r--r-- | chrome/common/notification_type.h | 4 | ||||
-rw-r--r-- | chrome/common/temp_scaffolding_stubs.cc | 5 | ||||
-rw-r--r-- | chrome/views/controls/native_control.cc | 1 | ||||
-rw-r--r-- | chrome/views/focus/focus_manager.cc | 20 | ||||
-rw-r--r-- | chrome/views/focus/focus_manager.h | 11 | ||||
-rw-r--r-- | chrome/views/focus/view_storage.cc | 41 | ||||
-rw-r--r-- | chrome/views/focus/view_storage.h | 16 | ||||
-rw-r--r-- | chrome/views/view_unittest.cc | 74 | ||||
-rw-r--r-- | chrome/views/views.vcproj | 4 | ||||
-rw-r--r-- | chrome/views/widget/root_view.cc | 25 | ||||
-rw-r--r-- | chrome/views/widget/widget_win.cc | 8 | ||||
-rw-r--r-- | chrome/views/window/window.h | 12 | ||||
-rw-r--r-- | chrome/views/window/window_win.cc | 54 | ||||
-rw-r--r-- | chrome/views/window/window_win.h | 17 |
20 files changed, 143 insertions, 179 deletions
diff --git a/chrome/browser/automation/automation_window_tracker.h b/chrome/browser/automation/automation_window_tracker.h index 1b9aff8..effa61e 100644 --- a/chrome/browser/automation/automation_window_tracker.h +++ b/chrome/browser/automation/automation_window_tracker.h @@ -13,7 +13,7 @@ // Since HWNDs aren't pointers, we can't have NativeWindow // be directly a pointer and so must explicitly declare the Source types // for it. -#include "chrome/views/widget/hwnd_notification_source.h" +#include "chrome/common/hwnd_notification_source.h" #elif defined(OS_LINUX) || defined(OS_MACOSX) // But on Linux and Mac, it is a pointer so this definition suffices. template<> diff --git a/chrome/browser/browser_list.cc b/chrome/browser/browser_list.cc index 3b6ee8b..034bba6 100644 --- a/chrome/browser/browser_list.cc +++ b/chrome/browser/browser_list.cc @@ -67,12 +67,8 @@ void BrowserList::RemoveBrowser(Browser* browser) { // If the last Browser object was destroyed, make sure we try to close any // remaining dependent windows too. - if (browsers_.empty()) { - NotificationService::current()->Notify( - NotificationType::ALL_APPWINDOWS_CLOSED, - NotificationService::AllSources(), - NotificationService::NoDetails()); - } + if (browsers_.empty()) + AllBrowsersClosed(); g_browser_process->ReleaseModule(); } diff --git a/chrome/browser/browser_list.h b/chrome/browser/browser_list.h index c73ac2e..f167fdc 100644 --- a/chrome/browser/browser_list.h +++ b/chrome/browser/browser_list.h @@ -115,6 +115,9 @@ class BrowserList { // Returns true if at least one off the record session is active. static bool IsOffTheRecordSessionActive(); + // Called when the last browser is closed. + static void AllBrowsersClosed(); + private: // Helper method to remove a browser instance from a list of browsers static void RemoveBrowserFrom(Browser* browser, list_type* browser_list); diff --git a/chrome/browser/views/frame/browser_view.cc b/chrome/browser/views/frame/browser_view.cc index 4d861f0..694c109 100644 --- a/chrome/browser/views/frame/browser_view.cc +++ b/chrome/browser/views/frame/browser_view.cc @@ -50,6 +50,7 @@ #include "chrome/browser/tab_contents/tab_contents_view.h" #include "chrome/browser/window_sizer.h" #include "chrome/common/chrome_switches.h" +#include "chrome/common/hwnd_notification_source.h" #include "chrome/common/notification_service.h" #include "chrome/common/pref_names.h" #include "chrome/common/pref_service.h" @@ -57,7 +58,6 @@ #include "chrome/views/controls/scrollbar/native_scroll_bar.h" #include "chrome/views/fill_layout.h" #include "chrome/views/view.h" -#include "chrome/views/widget/hwnd_notification_source.h" #include "chrome/views/widget/root_view.h" #include "chrome/views/window/non_client_view.h" #include "chrome/views/window/window_win.h" @@ -1666,3 +1666,8 @@ BrowserWindow* BrowserWindow::CreateBrowserWindow(Browser* browser) { FindBar* BrowserWindow::CreateFindBar(Browser* browser) { return new FindBarWin(static_cast<BrowserView*>(browser->window())); } + +// static +void BrowserList::AllBrowsersClosed() { + views::Window::CloseAllSecondaryWindows(); +} diff --git a/chrome/common/common.vcproj b/chrome/common/common.vcproj index 90b15d8..4c2d021 100644 --- a/chrome/common/common.vcproj +++ b/chrome/common/common.vcproj @@ -458,6 +458,10 @@ > </File> <File + RelativePath=".\hwnd_notification_source.h" + > + </File> + <File RelativePath=".\important_file_writer.cc" > </File> diff --git a/chrome/views/widget/hwnd_notification_source.h b/chrome/common/hwnd_notification_source.h index 602ae44..63df703 100644 --- a/chrome/views/widget/hwnd_notification_source.h +++ b/chrome/common/hwnd_notification_source.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_VIEWS_WIDGET_HWND_NOTIFICATION_SOURCE_H_ -#define CHROME_VIEWS_WIDGET_HWND_NOTIFICATION_SOURCE_H_ +#ifndef CHROME_COMMON_HWND_NOTIFICATION_SOURCE_H_ +#define CHROME_COMMON_HWND_NOTIFICATION_SOURCE_H_ #include "chrome/common/notification_source.h" @@ -21,4 +21,4 @@ class Source<HWND> : public NotificationSource { HWND ptr() const { return static_cast<HWND>(ptr_); } }; -#endif // #define CHROME_VIEWS_WIDGET_HWND_NOTIFICATION_SOURCE_H_ +#endif // #define CHROME_COMMON_HWND_NOTIFICATION_SOURCE_H_ diff --git a/chrome/common/notification_type.h b/chrome/common/notification_type.h index 1f67ec3..82d62e0 100644 --- a/chrome/common/notification_type.h +++ b/chrome/common/notification_type.h @@ -184,10 +184,6 @@ class NotificationType { // details are passed. ALL_APPWINDOWS_CLOSED, - // Indicates a new top window has been created. The source is the - // WindowWin. - WINDOW_CREATED, - // Indicates that a top window has been closed. The source is the HWND // that was closed, no details are expected. WINDOW_CLOSED, diff --git a/chrome/common/temp_scaffolding_stubs.cc b/chrome/common/temp_scaffolding_stubs.cc index b4d87c8..9706e26 100644 --- a/chrome/common/temp_scaffolding_stubs.cc +++ b/chrome/common/temp_scaffolding_stubs.cc @@ -312,3 +312,8 @@ void HungRendererDialog::HideForTabContents(TabContents*) { void HungRendererDialog::ShowForTabContents(TabContents*) { NOTIMPLEMENTED(); } + +void BrowserList::AllBrowsersClosed() { + // TODO(port): Close any dependent windows if necessary when the last browser + // window is closed. +} diff --git a/chrome/views/controls/native_control.cc b/chrome/views/controls/native_control.cc index 84a3226..bf40711 100644 --- a/chrome/views/controls/native_control.cc +++ b/chrome/views/controls/native_control.cc @@ -12,7 +12,6 @@ #include "app/l10n_util_win.h" #include "base/logging.h" #include "base/win_util.h" -#include "chrome/common/notification_service.h" #include "chrome/views/background.h" #include "chrome/views/border.h" #include "chrome/views/controls/hwnd_view.h" diff --git a/chrome/views/focus/focus_manager.cc b/chrome/views/focus/focus_manager.cc index 031cb0a..9e477e9 100644 --- a/chrome/views/focus/focus_manager.cc +++ b/chrome/views/focus/focus_manager.cc @@ -8,7 +8,6 @@ #include "base/logging.h" #include "base/win_util.h" #include "chrome/browser/renderer_host/render_widget_host_view_win.h" -#include "chrome/common/notification_service.h" #include "chrome/views/accelerator.h" #include "chrome/views/focus/focus_manager.h" #include "chrome/views/focus/view_storage.h" @@ -102,13 +101,6 @@ FocusManager* FocusManager::CreateFocusManager(HWND window, FocusManager* focus_manager = new FocusManager(window, root_view); SetProp(window, kFocusManagerKey, focus_manager); - // We register for view removed notifications so we can make sure we don't - // keep references to invalidated views. - NotificationService::current()->AddObserver( - focus_manager, - NotificationType::VIEW_REMOVED, - NotificationService::AllSources()); - return focus_manager; } @@ -212,11 +204,6 @@ bool FocusManager::OnNCDestroy(HWND window) { // We are the top window. DCHECK(GetProp(window, kFocusManagerKey)); - // Unregister notifications. - NotificationService::current()->RemoveObserver( - this, - NotificationType::VIEW_REMOVED, - NotificationService::AllSources()); // Make sure this is called on the window that was set with the // FocusManager. @@ -685,11 +672,8 @@ AcceleratorTarget* FocusManager::GetTargetForAccelerator( return NULL; } -void FocusManager::Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - DCHECK(type == NotificationType::VIEW_REMOVED); - if (focused_view_ && Source<View>(focused_view_) == source) +void FocusManager::ViewRemoved(View* parent, View* removed) { + if (focused_view_ && focused_view_ == removed) focused_view_ = NULL; } diff --git a/chrome/views/focus/focus_manager.h b/chrome/views/focus/focus_manager.h index 190385b..4a32c0d 100644 --- a/chrome/views/focus/focus_manager.h +++ b/chrome/views/focus/focus_manager.h @@ -13,7 +13,6 @@ #include <vector> #include <map> -#include "chrome/common/notification_observer.h" #include "chrome/views/accelerator.h" // The FocusManager class is used to handle focus traversal, store/restore @@ -152,7 +151,7 @@ class FocusChangeListener { virtual void FocusWillChange(View* focused_before, View* focused_now) = 0; }; -class FocusManager : public NotificationObserver { +class FocusManager { public: #if defined(OS_WIN) // Creates a FocusManager for the specified window. Top level windows @@ -264,10 +263,10 @@ class FocusManager : public NotificationObserver { // Returns true if an accelerator was activated. bool ProcessAccelerator(const Accelerator& accelerator); - // NotificationObserver method. - void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details); + // Called by a RootView when a view within its hierarchy is removed from its + // parent. This will only be called by a RootView in a hierarchy of Widgets + // that this FocusManager is attached to the parent Widget of. + void ViewRemoved(View* parent, View* removed); void AddKeystrokeListener(KeystrokeListener* listener); void RemoveKeystrokeListener(KeystrokeListener* listener); diff --git a/chrome/views/focus/view_storage.cc b/chrome/views/focus/view_storage.cc index 1a8324c..7299809 100644 --- a/chrome/views/focus/view_storage.cc +++ b/chrome/views/focus/view_storage.cc @@ -6,8 +6,8 @@ #include <algorithm> +#include "base/logging.h" #include "base/stl_util-inl.h" -#include "chrome/common/notification_service.h" namespace views { @@ -38,8 +38,6 @@ ViewStorage* ViewStorage::GetSharedInstance() { } ViewStorage::ViewStorage() : view_storage_next_id_(0) { - NotificationService::current()->AddObserver( - this, NotificationType::VIEW_REMOVED, NotificationService::AllSources()); } ViewStorage::~ViewStorage() { @@ -54,7 +52,7 @@ int ViewStorage::CreateStorageID() { return view_storage_next_id_++; } -void ViewStorage::StoreView(int storage_id, View* view) { +int ViewStorage::StoreView(int storage_id, View* view) { DCHECK(view); std::map<int, ViewLocationInfo*>::iterator iter = id_to_view_location_.find(storage_id); @@ -92,6 +90,7 @@ void ViewStorage::StoreView(int storage_id, View* view) { ids = id_iter->second; } ids->push_back(storage_id); + return storage_id; } View* ViewStorage::RetrieveView(int storage_id) { @@ -126,6 +125,21 @@ void ViewStorage::RemoveView(int storage_id) { EraseView(storage_id, false); } +void ViewStorage::ViewRemoved(View* parent, View* removed) { + // Let's first retrieve the ids for that view. + std::map<View*, std::vector<int>*>::iterator ids_iter = + view_to_ids_.find(removed); + + if (ids_iter == view_to_ids_.end()) { + // That view is not in the view storage. + return; + } + + std::vector<int>* ids = ids_iter->second; + DCHECK(!ids->empty()); + EraseView((*ids)[0], true); +} + void ViewStorage::EraseView(int storage_id, bool remove_all_ids) { // Remove the view from id_to_view_location_. std::map<int, ViewLocationInfo*>::iterator location_iter = @@ -166,23 +180,4 @@ void ViewStorage::EraseView(int storage_id, bool remove_all_ids) { } } -void ViewStorage::Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - DCHECK(type == NotificationType::VIEW_REMOVED); - - // Let's first retrieve the ids for that view. - std::map<View*, std::vector<int>*>::iterator ids_iter = - view_to_ids_.find(Source<View>(source).ptr()); - - if (ids_iter == view_to_ids_.end()) { - // That view is not in the view storage. - return; - } - - std::vector<int>* ids = ids_iter->second; - DCHECK(!ids->empty()); - EraseView((*ids)[0], true); -} - } // namespace views diff --git a/chrome/views/focus/view_storage.h b/chrome/views/focus/view_storage.h index cb0cb67..8ba9c9a 100644 --- a/chrome/views/focus/view_storage.h +++ b/chrome/views/focus/view_storage.h @@ -6,7 +6,6 @@ #define CHROME_VIEWS_FOCUS_VIEW_STORAGE_H_ #include "base/singleton.h" -#include "chrome/common/notification_observer.h" #include "chrome/views/view.h" // This class is a simple storage place for storing/retrieving views. It is @@ -26,7 +25,7 @@ namespace views { struct ViewLocationInfo; -class ViewStorage : public NotificationObserver { +class ViewStorage { public: // Returns the global ViewStorage instance. // It is guaranted to be non NULL. @@ -35,8 +34,9 @@ class ViewStorage : public NotificationObserver { // Returns a unique storage id that can be used to store/retrieve views. int CreateStorageID(); - // Associates |view| with the specified |storage_id|. - void StoreView(int storage_id, View* view); + // Associates |view| with the specified |storage_id|. Returns the + // |storage_id|. + int StoreView(int storage_id, View* view); // Returns the view associated with |storage_id| if any, NULL otherwise. View* RetrieveView(int storage_id); @@ -44,17 +44,15 @@ class ViewStorage : public NotificationObserver { // Removes the view associated with |storage_id| if any. void RemoveView(int storage_id); + // Notifies the ViewStorage that a view was removed from its parent somewhere. + void ViewRemoved(View* parent, View* removed); + private: friend struct DefaultSingletonTraits<ViewStorage>; ViewStorage(); ~ViewStorage(); - // NotificationObserver method. - void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details); - // Removes the view associated with |storage_id|. If |remove_all_ids| is true, // all other mapping pointing to the same view are removed as well. void EraseView(int storage_id, bool remove_all_ids); diff --git a/chrome/views/view_unittest.cc b/chrome/views/view_unittest.cc index da8c6ff..5b4f4ee 100644 --- a/chrome/views/view_unittest.cc +++ b/chrome/views/view_unittest.cc @@ -16,6 +16,7 @@ #include "chrome/views/controls/scroll_view.h" #include "chrome/views/controls/text_field.h" #include "chrome/views/event.h" +#include "chrome/views/focus/view_storage.h" #include "chrome/views/view.h" #include "chrome/views/widget/root_view.h" #include "chrome/views/widget/widget_win.h" @@ -430,96 +431,77 @@ TEST_F(ViewTest, DISABLED_Painting) { window.DestroyWindow(); } */ -typedef std::vector<View*> ViewList; - -class RemoveViewObserver : public NotificationObserver { -public: - RemoveViewObserver() { } - - void Observe(NotificationType type, const NotificationSource& source, - const NotificationDetails& details) { - ASSERT_TRUE(type == NotificationType::VIEW_REMOVED); - removed_views_.push_back(Source<views::View>(source).ptr()); - } - - bool WasRemoved(views::View* view) { - return std::find(removed_views_.begin(), removed_views_.end(), view) != - removed_views_.end(); - } - - ViewList removed_views_; - -}; TEST_F(ViewTest, RemoveNotification) { - scoped_ptr<RemoveViewObserver> observer(new RemoveViewObserver); - - NotificationService::current()->AddObserver( - observer.get(), - NotificationType::VIEW_REMOVED, - NotificationService::AllSources()); - + views::ViewStorage* vs = views::ViewStorage::GetSharedInstance(); views::WidgetWin* window = new views::WidgetWin; views::RootView* root_view = window->GetRootView(); View* v1 = new View; + int s1 = vs->StoreView(vs->CreateStorageID(), v1); root_view->AddChildView(v1); View* v11 = new View; + int s11 = vs->StoreView(vs->CreateStorageID(), v11); v1->AddChildView(v11); View* v111 = new View; + int s111 = vs->StoreView(vs->CreateStorageID(), v111); v11->AddChildView(v111); View* v112 = new View; + int s112 = vs->StoreView(vs->CreateStorageID(), v112); v11->AddChildView(v112); View* v113 = new View; + int s113 = vs->StoreView(vs->CreateStorageID(), v113); v11->AddChildView(v113); View* v1131 = new View; + int s1131 = vs->StoreView(vs->CreateStorageID(), v1131); v113->AddChildView(v1131); View* v12 = new View; + int s12 = vs->StoreView(vs->CreateStorageID(), v12); v1->AddChildView(v12); View* v2 = new View; + int s2 = vs->StoreView(vs->CreateStorageID(), v2); root_view->AddChildView(v2); View* v21 = new View; + int s21 = vs->StoreView(vs->CreateStorageID(), v21); v2->AddChildView(v21); View* v211 = new View; + int s211 = vs->StoreView(vs->CreateStorageID(), v211); v21->AddChildView(v211); // Try removing a leaf view. v21->RemoveChildView(v211); - EXPECT_EQ(1, observer->removed_views_.size()); - EXPECT_TRUE(observer->WasRemoved(v211)); + EXPECT_EQ(NULL, vs->RetrieveView(s211)); delete v211; // We won't use this one anymore. // Now try removing a view with a hierarchy of depth 1. - observer->removed_views_.clear(); v11->RemoveChildView(v113); - EXPECT_EQ(observer->removed_views_.size(), 2); - EXPECT_TRUE(observer->WasRemoved(v113) && observer->WasRemoved(v1131)); + EXPECT_EQ(NULL, vs->RetrieveView(s113)); + EXPECT_EQ(NULL, vs->RetrieveView(s1131)); delete v113; // We won't use this one anymore. // Now remove even more. - observer->removed_views_.clear(); root_view->RemoveChildView(v1); - EXPECT_EQ(observer->removed_views_.size(), 5); - EXPECT_TRUE(observer->WasRemoved(v1) && - observer->WasRemoved(v11) && observer->WasRemoved(v12) && - observer->WasRemoved(v111) && observer->WasRemoved(v112)); + EXPECT_EQ(NULL, vs->RetrieveView(s1)); + EXPECT_EQ(NULL, vs->RetrieveView(s11)); + EXPECT_EQ(NULL, vs->RetrieveView(s12)); + EXPECT_EQ(NULL, vs->RetrieveView(s111)); + EXPECT_EQ(NULL, vs->RetrieveView(s112)); // Put v1 back for more tests. root_view->AddChildView(v1); - observer->removed_views_.clear(); + vs->StoreView(s1, v1); // Now delete the root view (deleting the window will trigger a delete of the // RootView) and make sure we are notified that the views were removed. delete window; - EXPECT_EQ(observer->removed_views_.size(), 7); - EXPECT_TRUE(observer->WasRemoved(v1) && observer->WasRemoved(v2) && - observer->WasRemoved(v11) && observer->WasRemoved(v12) && - observer->WasRemoved(v21) && - observer->WasRemoved(v111) && observer->WasRemoved(v112)); - - NotificationService::current()->RemoveObserver(observer.get(), - NotificationType::VIEW_REMOVED, NotificationService::AllSources()); + EXPECT_EQ(NULL, vs->RetrieveView(s1)); + EXPECT_EQ(NULL, vs->RetrieveView(s12)); + EXPECT_EQ(NULL, vs->RetrieveView(s11)); + EXPECT_EQ(NULL, vs->RetrieveView(s12)); + EXPECT_EQ(NULL, vs->RetrieveView(s21)); + EXPECT_EQ(NULL, vs->RetrieveView(s111)); + EXPECT_EQ(NULL, vs->RetrieveView(s112)); } namespace { diff --git a/chrome/views/views.vcproj b/chrome/views/views.vcproj index 8e5d2fe..f972022 100644 --- a/chrome/views/views.vcproj +++ b/chrome/views/views.vcproj @@ -197,10 +197,6 @@ > </File> <File - RelativePath=".\widget\hwnd_notification_source.h" - > - </File> - <File RelativePath=".\widget\root_view.cc" > <FileConfiguration diff --git a/chrome/views/widget/root_view.cc b/chrome/views/widget/root_view.cc index bd57fe4..07680e6 100644 --- a/chrome/views/widget/root_view.cc +++ b/chrome/views/widget/root_view.cc @@ -13,11 +13,12 @@ #endif #include "base/logging.h" #include "base/message_loop.h" -#include "chrome/common/notification_service.h" #if defined(OS_WIN) +#include "chrome/views/focus/view_storage.h" #include "chrome/views/widget/root_view_drop_target.h" #endif #include "chrome/views/widget/widget.h" +#include "chrome/views/window/window.h" namespace views { @@ -261,10 +262,24 @@ void RootView::ViewHierarchyChanged(bool is_add, View* parent, View* child) { if (default_keyboard_handler_ == child) { default_keyboard_handler_ = NULL; } - NotificationService::current()->Notify( - NotificationType::VIEW_REMOVED, - Source<View>(child), - Details<View>(parent)); + + // For a given widget hierarchy, focus is tracked by a FocusManager attached + // to our nearest enclosing Window. <-- Important Assumption! + // We may not have access to our window if this function is called as a + // result of teardown during the deletion of the RootView and its hierarchy, + // so we don't bother notifying the FocusManager in that case because it + // will have already been destroyed (the Widget that contains us is + // NCDESTROY'ed which in turn destroys the focus manager _before_ the + // RootView is deleted.) +#if defined(OS_WIN) + Window* window = GetWindow(); + if (window) { + FocusManager* focus_manager = + FocusManager::GetFocusManager(window->GetNativeWindow()); + focus_manager->ViewRemoved(parent, child); + } + ViewStorage::GetSharedInstance()->ViewRemoved(parent, child); +#endif } } diff --git a/chrome/views/widget/widget_win.cc b/chrome/views/widget/widget_win.cc index 0bb3e78..5ee065a 100644 --- a/chrome/views/widget/widget_win.cc +++ b/chrome/views/widget/widget_win.cc @@ -9,14 +9,12 @@ #include "base/string_util.h" #include "base/win_util.h" #include "chrome/app/chrome_dll_resource.h" -#include "chrome/common/notification_service.h" #include "chrome/common/win_util.h" #include "chrome/views/accessibility/view_accessibility.h" #include "chrome/views/controls/native_control_win.h" #include "chrome/views/fill_layout.h" #include "chrome/views/focus/focus_util_win.h" #include "chrome/views/widget/aero_tooltip_manager.h" -#include "chrome/views/widget/hwnd_notification_source.h" #include "chrome/views/widget/root_view.h" #include "chrome/views/window/window_win.h" @@ -467,12 +465,6 @@ void WidgetWin::OnCaptureChanged(HWND hwnd) { } void WidgetWin::OnClose() { - // WARNING: this method is NOT called for all WidgetWins. If you need to do - // cleanup code before WidgetWin is destroyed, put it in OnDestroy. - NotificationService::current()->Notify( - NotificationType::WINDOW_CLOSED, Source<HWND>(hwnd_), - NotificationService::NoDetails()); - Close(); } diff --git a/chrome/views/window/window.h b/chrome/views/window/window.h index fe820da..819f31c 100644 --- a/chrome/views/window/window.h +++ b/chrome/views/window/window.h @@ -39,6 +39,11 @@ class Window { static gfx::Size GetLocalizedContentsSize(int col_resource_id, int row_resource_id); + // Closes all windows that aren't identified as "app windows" via + // IsAppWindow. Called during application shutdown when the last "app window" + // is closed. + static void CloseAllSecondaryWindows(); + // Retrieves the window's bounds, including its frame. virtual gfx::Rect GetBounds() const = 0; @@ -47,7 +52,7 @@ class Window { // Sizes and/or places the window to the specified bounds, size or position. virtual void SetBounds(const gfx::Rect& bounds) = 0; - + // As above, except the window is inserted after |other_window| in the window // Z-order. If this window is not yet visible, other_window's monitor is used // as the constraining rectangle, rather than this window's monitor. @@ -85,6 +90,11 @@ class Window { virtual void SetFullscreen(bool fullscreen) = 0; virtual bool IsFullscreen() const = 0; + // Returns true if the Window is considered to be an "app window" - i.e. + // any window which when it is the last of its type closed causes the + // application to exit. + virtual bool IsAppWindow() const { return false; } + // Toggles the enable state for the Close button (and the Close menu item in // the system menu). virtual void EnableClose(bool enable) = 0; diff --git a/chrome/views/window/window_win.cc b/chrome/views/window/window_win.cc index 7b0c528..73be950 100644 --- a/chrome/views/window/window_win.cc +++ b/chrome/views/window/window_win.cc @@ -14,7 +14,6 @@ #include "app/resource_bundle.h" #include "base/win_util.h" #include "chrome/app/chrome_dll_resource.h" -#include "chrome/common/notification_service.h" #include "chrome/common/win_util.h" #include "chrome/views/widget/root_view.h" #include "chrome/views/window/client_view.h" @@ -429,19 +428,6 @@ gfx::NativeWindow WindowWin::GetNativeWindow() const { return GetNativeView(); } -//////////////////////////////////////////////////////////////////////////////// -// WindowWin, NotificationObserver implementation: - -void WindowWin::Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - // This window is closed when the last app window is closed. - DCHECK(type == NotificationType::ALL_APPWINDOWS_CLOSED); - // Only registered as an observer when we're not an app window. - // XXX DCHECK(!IsAppWindow()); - Close(); -} - /////////////////////////////////////////////////////////////////////////////// // WindowWin, protected: @@ -507,20 +493,7 @@ void WindowWin::Init(HWND parent, const gfx::Rect& bounds) { GetMonitorAndRects(bounds.ToRECT(), &last_monitor_, &last_monitor_rect_, &last_work_area_); - - if (!IsAppWindow()) { - notification_registrar_.Add( - this, - NotificationType::ALL_APPWINDOWS_CLOSED, - NotificationService::AllSources()); - } - ResetWindowRegion(false); - - NotificationService::current()->Notify( - NotificationType::WINDOW_CREATED, - Source<WindowWin>(this), - NotificationService::NoDetails()); } void WindowWin::SizeWindowToDefault() { @@ -1443,4 +1416,31 @@ void WindowWin::InitClass() { } } +namespace { +// static +static BOOL CALLBACK WindowCallbackProc(HWND hwnd, LPARAM lParam) { + WidgetWin* widget = reinterpret_cast<WidgetWin*>( + win_util::GetWindowUserData(hwnd)); + if (!widget) + return TRUE; + + // If the toplevel HWND is a Window, close it if it's identified as a + // secondary window. + Window* window = widget->GetWindow(); + if (window) { + if (!window->IsAppWindow()) + window->Close(); + } else { + // If it's not a Window, then close it anyway since it probably is + // secondary. + widget->Close(); + } + return TRUE; +} +} // namespace + +void Window::CloseAllSecondaryWindows() { + EnumThreadWindows(GetCurrentThreadId(), WindowCallbackProc, 0); +} + } // namespace views diff --git a/chrome/views/window/window_win.h b/chrome/views/window/window_win.h index 239e17e..749ae94 100644 --- a/chrome/views/window/window_win.h +++ b/chrome/views/window/window_win.h @@ -5,7 +5,6 @@ #ifndef CHROME_VIEWS_WINDOW_WINDOW_WIN_H__ #define CHROME_VIEWS_WINDOW_WINDOW_WIN_H__ -#include "chrome/common/notification_registrar.h" #include "chrome/views/widget/widget_win.h" #include "chrome/views/window/client_view.h" #include "chrome/views/window/non_client_view.h" @@ -30,8 +29,7 @@ class WindowDelegate; // /////////////////////////////////////////////////////////////////////////////// class WindowWin : public WidgetWin, - public Window, - public NotificationObserver { + public Window { public: virtual ~WindowWin(); @@ -91,11 +89,6 @@ class WindowWin : public WidgetWin, virtual ClientView* GetClientView() const; virtual gfx::NativeWindow GetNativeWindow() const; - // NotificationObserver overrides: - virtual void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details); - protected: friend Window; @@ -111,11 +104,6 @@ class WindowWin : public WidgetWin, // Sizes the window to the default size specified by its ClientView. virtual void SizeWindowToDefault(); - // Returns true if the WindowWin is considered to be an "app window" - i.e. - // any window which when it is the last of its type closed causes the - // application to exit. - virtual bool IsAppWindow() const { return false; } - // Shows the system menu at the specified screen point. void RunSystemMenu(const gfx::Point& point); @@ -311,9 +299,6 @@ class WindowWin : public WidgetWin, HMONITOR last_monitor_; gfx::Rect last_monitor_rect_, last_work_area_; - // Hold onto notifications. - NotificationRegistrar notification_registrar_; - DISALLOW_COPY_AND_ASSIGN(WindowWin); }; |