Index: ash/shelf/shelf_window_watcher.cc |
diff --git a/ash/shelf/shelf_window_watcher.cc b/ash/shelf/shelf_window_watcher.cc |
index b4e65e25a7b2f50761de5c0c524936e86163917c..b60484fb19df6080c52c828d8ccc023c1d6211e8 100644 |
--- a/ash/shelf/shelf_window_watcher.cc |
+++ b/ash/shelf/shelf_window_watcher.cc |
@@ -11,6 +11,7 @@ |
#include "ash/shelf/shelf_window_watcher_item_delegate.h" |
#include "ash/shell.h" |
#include "ash/shell_window_ids.h" |
+#include "ash/wm/window_state.h" |
#include "ash/wm/window_util.h" |
#include "base/memory/scoped_ptr.h" |
#include "ui/aura/client/activation_client.h" |
@@ -40,6 +41,11 @@ bool HasLauncherItemForWindow(aura::Window* window) { |
return false; |
} |
+// Returns true if |window| is in the process of being dragged. |
+bool IsDragging(aura::Window* window) { |
+ return ash::wm::GetWindowState(window)->is_dragged(); |
+} |
+ |
} // namespace |
namespace ash { |
@@ -58,14 +64,53 @@ void ShelfWindowWatcher::RootWindowObserver::OnWindowDestroying( |
window_watcher_->OnRootWindowRemoved(window); |
} |
+ShelfWindowWatcher::RemovedWindowObserver::RemovedWindowObserver( |
+ ShelfWindowWatcher* window_watcher) |
+ : window_watcher_(window_watcher) { |
+} |
+ |
+ShelfWindowWatcher::RemovedWindowObserver::~RemovedWindowObserver() { |
+} |
+ |
+void ShelfWindowWatcher::RemovedWindowObserver::OnWindowParentChanged( |
+ aura::Window* window, |
+ aura::Window* parent) { |
+ // When |parent| is NULL, this |window| will be destroyed. In that case, its |
+ // item will be removed at OnWindowDestroyed(). |
+ if (!parent) |
+ return; |
+ |
+ aura::Window* root_window = window->GetRootWindow(); |
+ aura::Window* docked_container = Shell::GetContainer( |
+ root_window, |
+ kShellWindowId_DockedContainer); |
+ |
+ // When |parent| is changed from default container to |docked_container| |
+ // during the dragging, |window|'s item should not be removed. Otherwise, |
+ // Remove it. |
+ if ((IsDragging(window) && parent == docked_container)) |
simonhong
2013/12/18 07:13:41
We should check IsDragging() and its parent is |do
|
+ return; |
+ |
+ // When |window| is re-parented to other containers or |window| is re-parented |
+ // not to |docked_container| during the dragging, its item should be removed. |
+ window_watcher_->FinalizeItemOfRemovedWindow(window); |
+} |
+ |
+void ShelfWindowWatcher::RemovedWindowObserver::OnWindowDestroyed( |
+ aura::Window* window) { |
+ window_watcher_->FinalizeItemOfRemovedWindow(window); |
+} |
+ |
ShelfWindowWatcher::ShelfWindowWatcher( |
ShelfModel* model, |
ShelfItemDelegateManager* item_delegate_manager) |
: model_(model), |
item_delegate_manager_(item_delegate_manager), |
root_window_observer_(this), |
+ removed_window_observer_(this), |
observed_windows_(this), |
observed_root_windows_(&root_window_observer_), |
+ observed_removed_windows_(&removed_window_observer_), |
observed_activation_clients_(this) { |
// We can't assume all RootWindows have the same ActivationClient. |
// Add a RootWindow and its ActivationClient to the observed list. |
@@ -137,6 +182,11 @@ int ShelfWindowWatcher::GetLauncherItemIndexForWindow( |
return model_->ItemIndexByID(GetLauncherIDForWindow(window)); |
} |
+void ShelfWindowWatcher::FinalizeItemOfRemovedWindow(aura::Window* window) { |
+ observed_removed_windows_.Remove(window); |
+ RemoveLauncherItem(window); |
+} |
+ |
void ShelfWindowWatcher::OnWindowActivated(aura::Window* gained_active, |
aura::Window* lost_active) { |
if (gained_active && HasLauncherItemForWindow(gained_active)) |
@@ -147,6 +197,15 @@ void ShelfWindowWatcher::OnWindowActivated(aura::Window* gained_active, |
void ShelfWindowWatcher::OnWindowAdded(aura::Window* window) { |
observed_windows_.Add(window); |
+ |
+ if (observed_removed_windows_.IsObserving(window)) { |
+ // When |window| is added and it is already observed by |
+ // |dragged_window_observer_|, |window| already has its item. |
+ DCHECK(HasLauncherItemForWindow(window)); |
+ observed_removed_windows_.Remove(window); |
+ return; |
+ } |
+ |
// Add LauncherItem if |window| already has a LauncherItemDetails when it is |
// created. Don't make a new LauncherItem for the re-parented |window| that |
// already has a LauncherItem. |
@@ -156,12 +215,14 @@ void ShelfWindowWatcher::OnWindowAdded(aura::Window* window) { |
} |
void ShelfWindowWatcher::OnWillRemoveWindow(aura::Window* window) { |
- // Remove a child window of default container and its item if it has. |
+ // Remove a child window of default container. |
if (observed_windows_.IsObserving(window)) |
observed_windows_.Remove(window); |
+ // Defer handling of removing |window|'s item to RemovedWindowObserver because |
+ // |window| could be added again to default container. |
if (HasLauncherItemForWindow(window)) |
- RemoveLauncherItem(window); |
+ observed_removed_windows_.Add(window); |
} |
void ShelfWindowWatcher::OnWindowDestroying(aura::Window* window) { |