From 264f085afba2758294636556a236ff760ba17e93 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 2 May 2013 22:54:09 +0800 Subject: [PATCH] Add WindowList class to manage all windows. --- atom.gyp | 3 ++ browser/atom_application.mm | 10 +++-- browser/native_window.cc | 13 +++--- browser/native_window.h | 7 ---- browser/window_list.cc | 77 ++++++++++++++++++++++++++++++++++ browser/window_list.h | 66 +++++++++++++++++++++++++++++ browser/window_list_observer.h | 30 +++++++++++++ 7 files changed, 187 insertions(+), 19 deletions(-) create mode 100644 browser/window_list.cc create mode 100644 browser/window_list.h create mode 100644 browser/window_list_observer.h diff --git a/atom.gyp b/atom.gyp index f9ad09bc4287..0ed0ea98e80e 100644 --- a/atom.gyp +++ b/atom.gyp @@ -51,6 +51,9 @@ 'browser/native_window_mac.h', 'browser/native_window_mac.mm', 'browser/native_window_observer.h', + 'browser/window_list.cc', + 'browser/window_list.h', + 'browser/window_list_observer.h', 'common/api/api_messages.cc', 'common/api/api_messages.h', 'common/api/atom_api_clipboard.cc', diff --git a/browser/atom_application.mm b/browser/atom_application.mm index 3a377bc69222..d52e835db60c 100644 --- a/browser/atom_application.mm +++ b/browser/atom_application.mm @@ -6,7 +6,7 @@ #include "base/auto_reset.h" #include "base/logging.h" -#include "browser/native_window.h" +#include "browser/window_list.h" @implementation AtomApplication @@ -28,9 +28,11 @@ } - (IBAction)closeAllWindows:(id)sender { - std::vector windows = atom::NativeWindow::windows(); - for (size_t i = 0; i < windows.size(); ++i) - windows[i]->Close(); + atom::WindowList* window_list = atom::WindowList::GetInstance(); + if (window_list->size() == 0) + [self terminate:self]; + + window_list->CloseAllWindows(); } @end diff --git a/browser/native_window.cc b/browser/native_window.cc index 13af679beeb1..ff0bfce71965 100644 --- a/browser/native_window.cc +++ b/browser/native_window.cc @@ -4,7 +4,6 @@ #include "browser/native_window.h" -#include #include #include "base/utf_string_conversions.h" @@ -15,6 +14,7 @@ #include "browser/atom_browser_context.h" #include "browser/atom_browser_main_parts.h" #include "browser/atom_javascript_dialog_manager.h" +#include "browser/window_list.h" #include "content/public/browser/navigation_entry.h" #include "content/public/browser/notification_details.h" #include "content/public/browser/notification_source.h" @@ -32,9 +32,6 @@ using content::NavigationEntry; namespace atom { -// static -std::vector NativeWindow::windows_; - NativeWindow::NativeWindow(content::WebContents* web_contents, base::DictionaryValue* options) : content::WebContentsObserver(web_contents), @@ -43,7 +40,7 @@ NativeWindow::NativeWindow(content::WebContents* web_contents, brightray::InspectableWebContents::Create(web_contents)) { web_contents->SetDelegate(this); - windows_.push_back(this); + WindowList::AddWindow(this); // Get notified of title updated message. registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED, @@ -66,7 +63,8 @@ NativeWindow* NativeWindow::Create(base::DictionaryValue* options) { NativeWindow* NativeWindow::FromProcessIDAndRoutingID(int process_id, int routing_id) { // Stupid iterating. - for (auto window : windows_) { + WindowList& window_list = *WindowList::GetInstance(); + for (auto window : window_list) { content::WebContents* web_contents = window->GetWebContents(); int window_process_id = web_contents->GetRenderProcessHost()->GetID(); int window_routing_id = web_contents->GetRoutingID(); @@ -160,8 +158,7 @@ void NativeWindow::NotifyWindowClosed() { return; is_closed_ = true; - windows_.erase(std::remove(windows_.begin(), windows_.end(), this), - windows_.end()); + WindowList::RemoveWindow(this); FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnWindowClosed()); } diff --git a/browser/native_window.h b/browser/native_window.h index da971a979b9a..acc563833518 100644 --- a/browser/native_window.h +++ b/browser/native_window.h @@ -6,7 +6,6 @@ #define ATOM_BROWSER_NATIVE_WINDOW_H_ #include -#include #include "base/basictypes.h" #include "base/compiler_specific.h" @@ -59,9 +58,6 @@ class NativeWindow : public content::WebContentsDelegate, static NativeWindow* FromProcessIDAndRoutingID(int process_id, int routing_id); - // Return all opened windows. - static std::vector windows() { return windows_; } - void InitFromOptions(base::DictionaryValue* options); virtual void Close() = 0; @@ -156,9 +152,6 @@ class NativeWindow : public content::WebContentsDelegate, // Observers of this window. ObserverList observers_; - // Stores all windows. - static std::vector windows_; - bool is_closed_; scoped_ptr dialog_manager_; diff --git a/browser/window_list.cc b/browser/window_list.cc new file mode 100644 index 000000000000..4d63b2e33d70 --- /dev/null +++ b/browser/window_list.cc @@ -0,0 +1,77 @@ +// Copyright (c) 2013 GitHub, Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "browser/window_list.h" + +#include + +#include "base/logging.h" +#include "browser/native_window.h" +#include "browser/window_list_observer.h" + +namespace atom { + +// static +base::LazyInstance>::Leaky + WindowList::observers_ = LAZY_INSTANCE_INITIALIZER; + +// static +WindowList* WindowList::instance_ = NULL; + +// static +WindowList* WindowList::GetInstance() { + if (!instance_) + instance_ = new WindowList; + return instance_; +} + +// static +void WindowList::AddWindow(NativeWindow* window) { + DCHECK(window); + // Push |window| on the appropriate list instance. + WindowVector& windows = GetInstance()->windows_; + windows.push_back(window); + + FOR_EACH_OBSERVER(WindowListObserver, observers_.Get(), + OnWindowAdded(window)); +} + +// static +void WindowList::RemoveWindow(NativeWindow* window) { + WindowVector& windows = GetInstance()->windows_; + windows.erase(std::remove(windows.begin(), windows.end(), window), + windows.end()); + + FOR_EACH_OBSERVER(WindowListObserver, observers_.Get(), + OnWindowRemoved(window)); + + if (windows.size() == 0) + FOR_EACH_OBSERVER(WindowListObserver, observers_.Get(), + OnWindowAllClosed()); +} + +// static +void WindowList::AddObserver(WindowListObserver* observer) { + observers_.Get().AddObserver(observer); +} + +// static +void WindowList::RemoveObserver(WindowListObserver* observer) { + observers_.Get().RemoveObserver(observer); +} + +// static +void WindowList::CloseAllWindows() { + WindowVector windows = GetInstance()->windows_; + for (size_t i = 0; i < windows.size(); ++i) + windows[i]->Close(); +} + +WindowList::WindowList() { +} + +WindowList::~WindowList() { +} + +} // namespace atom diff --git a/browser/window_list.h b/browser/window_list.h new file mode 100644 index 000000000000..0b9f0f9706d7 --- /dev/null +++ b/browser/window_list.h @@ -0,0 +1,66 @@ +// Copyright (c) 2013 GitHub, Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROWSER_WINDOW_LIST_H_ +#define ATOM_BROWSER_WINDOW_LIST_H_ + +#include + +#include "base/basictypes.h" +#include "base/lazy_instance.h" +#include "base/observer_list.h" + +namespace atom { + +class NativeWindow; +class WindowListObserver; + +class WindowList { + public: + typedef std::vector WindowVector; + typedef WindowVector::const_iterator const_iterator; + typedef WindowVector::const_reverse_iterator const_reverse_iterator; + + // Windows are added to the list before they have constructed windows, + // so the |window()| member function may return NULL. + const_iterator begin() const { return windows_.begin(); } + const_iterator end() const { return windows_.end(); } + + bool empty() const { return windows_.empty(); } + size_t size() const { return windows_.size(); } + + NativeWindow* get(size_t index) const { return windows_[index]; } + + static WindowList* GetInstance(); + + // Adds or removes |window| from the list it is associated with. + static void AddWindow(NativeWindow* window); + static void RemoveWindow(NativeWindow* window); + + // Adds and removes |observer| from the observer list. + static void AddObserver(WindowListObserver* observer); + static void RemoveObserver(WindowListObserver* observer); + + // Closes all windows. + static void CloseAllWindows(); + + private: + WindowList(); + ~WindowList(); + + // A vector of the windows in this list, in the order they were added. + WindowVector windows_; + + // A list of observers which will be notified of every window addition and + // removal across all WindowLists. + static base::LazyInstance>::Leaky observers_; + + static WindowList* instance_; + + DISALLOW_COPY_AND_ASSIGN(WindowList); +}; + +} // namespace atom + +#endif // ATOM_BROWSER_WINDOW_LIST_H_ diff --git a/browser/window_list_observer.h b/browser/window_list_observer.h new file mode 100644 index 000000000000..ed7fa846a657 --- /dev/null +++ b/browser/window_list_observer.h @@ -0,0 +1,30 @@ +// Copyright (c) 2013 GitHub, Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROSER_WINDOW_LIST_OBSERVER_H_ +#define ATOM_BROSER_WINDOW_LIST_OBSERVER_H_ + +namespace atom { + +class NativeWindow; + +class WindowListObserver { + public: + // Called immediately after a window is added to the list. + virtual void OnWindowAdded(NativeWindow* window) {} + + // Called immediately after a window is removed from the list. + virtual void OnWindowRemoved(NativeWindow* window) {} + + // Called immediately after all windows are closed. + virtual void OnWindowAllClosed() {} + + protected: + virtual ~WindowListObserver() {} +}; + + +} // namespace atom + +#endif // ATOM_BROSER_WINDOW_LIST_OBSERVER_H_