summaryrefslogtreecommitdiffstats
path: root/ash
diff options
context:
space:
mode:
authorflackr@chromium.org <flackr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-02-26 05:33:29 +0000
committerflackr@chromium.org <flackr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-02-26 05:33:29 +0000
commit5b602190c3a6b949cfb74157e8b7c1ecf61bed36 (patch)
treea9a140196363fac1152c1520c57a7111c8787084 /ash
parent9c233029a88b2b529a119f951361cb803987d5c1 (diff)
downloadchromium_src-5b602190c3a6b949cfb74157e8b7c1ecf61bed36.zip
chromium_src-5b602190c3a6b949cfb74157e8b7c1ecf61bed36.tar.gz
chromium_src-5b602190c3a6b949cfb74157e8b7c1ecf61bed36.tar.bz2
Create a separate callout widget per panel which displays over each icon.
BUG=162960 TEST=PanelManagerLayoutTest.MinimizeRestorePanel, PanelManagerLayoutTest.MultiplePanelCallout, RootWindowControllerTest.MoveWindows_Basic Review URL: https://chromiumcodereview.appspot.com/12282046 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@184593 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ash')
-rw-r--r--ash/root_window_controller.cc24
-rw-r--r--ash/wm/panel_layout_manager.cc136
-rw-r--r--ash/wm/panel_layout_manager.h38
-rw-r--r--ash/wm/panel_layout_manager_unittest.cc38
4 files changed, 128 insertions, 108 deletions
diff --git a/ash/root_window_controller.cc b/ash/root_window_controller.cc
index 71c9101..dcb3bab 100644
--- a/ash/root_window_controller.cc
+++ b/ash/root_window_controller.cc
@@ -134,16 +134,20 @@ void ReparentAllWindows(aura::RootWindow* src, aura::RootWindow* dst) {
aura::Window* src_container = Shell::GetContainer(src, id);
aura::Window* dst_container = Shell::GetContainer(dst, id);
- aura::Window::Windows children = src_container->children();
- for (aura::Window::Windows::iterator iter = children.begin();
- iter != children.end(); ++iter) {
- aura::Window* window = *iter;
- // Don't move modal screen.
- if (internal::SystemModalContainerLayoutManager::IsModalBackground(
- window))
- continue;
-
- ReparentWindow(window, dst_container);
+ while (!src_container->children().empty()) {
+ // Restart iteration from the source container windows each time as they
+ // may change as a result of moving other windows.
+ aura::Window::Windows::const_iterator iter =
+ src_container->children().begin();
+ while (iter != src_container->children().end() &&
+ internal::SystemModalContainerLayoutManager::IsModalBackground(
+ *iter)) {
+ ++iter;
+ }
+ // If the entire window list is modal background windows then stop.
+ if (iter == src_container->children().end())
+ break;
+ ReparentWindow(*iter, dst_container);
}
}
}
diff --git a/ash/wm/panel_layout_manager.cc b/ash/wm/panel_layout_manager.cc
index b7b6fc4..54df0c2 100644
--- a/ash/wm/panel_layout_manager.cc
+++ b/ash/wm/panel_layout_manager.cc
@@ -128,32 +128,14 @@ PanelLayoutManager::PanelLayoutManager(aura::Window* panel_container)
dragged_panel_(NULL),
launcher_(NULL),
last_active_panel_(NULL),
- callout_widget_(new views::Widget),
weak_factory_(this) {
DCHECK(panel_container);
- views::Widget::InitParams params;
- params.type = views::Widget::InitParams::TYPE_POPUP;
- params.transparent = true;
- params.can_activate = false;
- params.keep_on_top = true;
- params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- params.parent = panel_container_;
- params.bounds = ScreenAsh::ConvertRectToScreen(panel_container_, gfx::Rect());
- params.bounds.set_width(kArrowWidth);
- params.bounds.set_height(kArrowHeight);
- // Why do we need this and can_activate = false?
- callout_widget_->set_focus_on_creation(false);
- callout_widget_->Init(params);
- DCHECK_EQ(callout_widget_->GetNativeView()->GetRootWindow(),
- panel_container_->GetRootWindow());
- views::View* content_view = new views::View;
- content_view->set_background(new CalloutWidgetBackground);
- callout_widget_->SetContentsView(content_view);
aura::client::GetActivationClient(Shell::GetPrimaryRootWindow())->
AddObserver(this);
}
PanelLayoutManager::~PanelLayoutManager() {
+ Shutdown();
if (launcher_)
launcher_->RemoveIconObserver(this);
aura::client::GetActivationClient(Shell::GetPrimaryRootWindow())->
@@ -161,7 +143,11 @@ PanelLayoutManager::~PanelLayoutManager() {
}
void PanelLayoutManager::Shutdown() {
- callout_widget_.reset();
+ for (PanelList::iterator iter = panel_windows_.begin();
+ iter != panel_windows_.end(); ++iter) {
+ delete iter->callout_widget;
+ }
+ panel_windows_.clear();
}
void PanelLayoutManager::StartDragging(aura::Window* panel) {
@@ -200,9 +186,12 @@ void PanelLayoutManager::OnWindowResized() {
}
void PanelLayoutManager::OnWindowAddedToLayout(aura::Window* child) {
- if (callout_widget_ && child == callout_widget_->GetNativeWindow())
+ if (child->type() == aura::client::WINDOW_TYPE_POPUP)
return;
- panel_windows_.push_back(child);
+ PanelInfo panel_info;
+ panel_info.window = child;
+ panel_info.callout_widget = CreateCalloutWidget();
+ panel_windows_.push_back(panel_info);
child->AddObserver(this);
Relayout();
}
@@ -211,10 +200,14 @@ void PanelLayoutManager::OnWillRemoveWindowFromLayout(aura::Window* child) {
}
void PanelLayoutManager::OnWindowRemovedFromLayout(aura::Window* child) {
+ if (child->type() == aura::client::WINDOW_TYPE_POPUP)
+ return;
PanelList::iterator found =
std::find(panel_windows_.begin(), panel_windows_.end(), child);
- if (found != panel_windows_.end())
+ if (found != panel_windows_.end()) {
+ delete found->callout_widget;
panel_windows_.erase(found);
+ }
child->RemoveObserver(this);
if (dragged_panel_ == child)
@@ -251,12 +244,13 @@ void PanelLayoutManager::SetChildBounds(aura::Window* child,
for (new_position = panel_windows_.begin();
new_position != panel_windows_.end();
++new_position) {
- const gfx::Rect& bounds = (*new_position)->bounds();
+ const gfx::Rect& bounds = (*new_position).window->bounds();
if (bounds.x() + bounds.width()/2 <= requested_bounds.x()) break;
}
if (new_position != dragged_panel_iter) {
+ PanelInfo dragged_panel_info = *dragged_panel_iter;
panel_windows_.erase(dragged_panel_iter);
- panel_windows_.insert(new_position, dragged_panel_);
+ panel_windows_.insert(new_position, dragged_panel_info);
}
}
@@ -306,10 +300,8 @@ void PanelLayoutManager::OnWindowActivated(aura::Window* gained_active,
gained_active->type() == aura::client::WINDOW_TYPE_PANEL &&
gained_active->parent() == panel_container_) {
UpdateStacking(gained_active);
- UpdateCallout(gained_active);
- } else {
- UpdateCallout(NULL);
}
+ UpdateCallouts();
}
////////////////////////////////////////////////////////////////////////////////
@@ -345,7 +337,7 @@ void PanelLayoutManager::Relayout() {
std::vector<VisiblePanelPositionInfo> visible_panels;
for (PanelList::iterator iter = panel_windows_.begin();
iter != panel_windows_.end(); ++iter) {
- aura::Window* panel = *iter;
+ aura::Window* panel = iter->window;
if (!panel->IsVisible() || panel == dragged_panel_)
continue;
@@ -407,7 +399,7 @@ void PanelLayoutManager::Relayout() {
}
UpdateStacking(active_panel);
- UpdateCallout(active_panel);
+ UpdateCallouts();
}
void PanelLayoutManager::UpdateStacking(aura::Window* active_panel) {
@@ -429,9 +421,9 @@ void PanelLayoutManager::UpdateStacking(aura::Window* active_panel) {
std::map<int, aura::Window*> window_ordering;
for (PanelList::const_iterator it = panel_windows_.begin();
it != panel_windows_.end(); ++it) {
- gfx::Rect bounds = (*it)->bounds();
+ gfx::Rect bounds = it->window->bounds();
window_ordering.insert(std::make_pair(bounds.x() + bounds.width() / 2,
- *it));
+ it->window));
}
aura::Window* previous_panel = NULL;
@@ -456,41 +448,57 @@ void PanelLayoutManager::UpdateStacking(aura::Window* active_panel) {
last_active_panel_ = active_panel;
}
-void PanelLayoutManager::UpdateCallout(aura::Window* active_panel) {
- weak_factory_.InvalidateWeakPtrs();
- // TODO(dcheng): This doesn't account for panels in overflow. They should have
- // a callout as well.
- if (!active_panel ||
- launcher_->GetScreenBoundsOfItemIconForWindow(active_panel).IsEmpty()) {
- if (callout_widget_)
- callout_widget_->Hide();
- return;
+void PanelLayoutManager::UpdateCallouts() {
+ for (PanelList::iterator iter = panel_windows_.begin();
+ iter != panel_windows_.end(); ++iter) {
+ aura::Window* panel = iter->window;
+ views::Widget* callout_widget = iter->callout_widget;
+
+ gfx::Rect bounds = panel->GetBoundsInRootWindow();
+ gfx::Rect icon_bounds =
+ launcher_->GetScreenBoundsOfItemIconForWindow(panel);
+ if (icon_bounds.IsEmpty() || !panel->IsVisible() ||
+ panel == dragged_panel_) {
+ callout_widget->Hide();
+ continue;
+ }
+
+ gfx::Rect callout_bounds = callout_widget->GetWindowBoundsInScreen();
+ callout_bounds.set_x(
+ icon_bounds.x() + (icon_bounds.width() - callout_bounds.width()) / 2);
+ callout_bounds.set_y(bounds.bottom());
+ callout_bounds = ScreenAsh::ConvertRectFromScreen(
+ callout_widget->GetNativeWindow()->parent(),
+ callout_bounds);
+
+ SetChildBoundsDirect(callout_widget->GetNativeWindow(), callout_bounds);
+ panel_container_->StackChildAbove(callout_widget->GetNativeWindow(),
+ panel);
+ callout_widget->Show();
}
- MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&PanelLayoutManager::ShowCalloutHelper,
- weak_factory_.GetWeakPtr(),
- active_panel));
}
-void PanelLayoutManager::ShowCalloutHelper(aura::Window* active_panel) {
- if (!callout_widget_)
- return;
- DCHECK(active_panel);
- gfx::Rect bounds = active_panel->GetBoundsInRootWindow();
- gfx::Rect icon_bounds =
- launcher_->GetScreenBoundsOfItemIconForWindow(active_panel);
- gfx::Rect callout_bounds = callout_widget_->GetWindowBoundsInScreen();
- callout_bounds.set_x(
- icon_bounds.x() + (icon_bounds.width() - callout_bounds.width()) / 2);
- callout_bounds.set_y(bounds.bottom());
- callout_bounds = ScreenAsh::ConvertRectFromScreen(
- callout_widget_->GetNativeWindow()->parent(),
- callout_bounds);
-
- SetChildBoundsDirect(callout_widget_->GetNativeWindow(), callout_bounds);
- panel_container_->StackChildAtTop(callout_widget_->GetNativeWindow());
- callout_widget_->Show();
+views::Widget* PanelLayoutManager::CreateCalloutWidget() {
+ views::Widget* callout_widget = new views::Widget;
+ views::Widget::InitParams params;
+ params.type = views::Widget::InitParams::TYPE_POPUP;
+ params.transparent = true;
+ params.can_activate = false;
+ params.keep_on_top = true;
+ params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ params.parent = panel_container_;
+ params.bounds = ScreenAsh::ConvertRectToScreen(panel_container_, gfx::Rect());
+ params.bounds.set_width(kArrowWidth);
+ params.bounds.set_height(kArrowHeight);
+ // Why do we need this and can_activate = false?
+ callout_widget->set_focus_on_creation(false);
+ callout_widget->Init(params);
+ DCHECK_EQ(callout_widget->GetNativeView()->GetRootWindow(),
+ panel_container_->GetRootWindow());
+ views::View* content_view = new views::View;
+ content_view->set_background(new CalloutWidgetBackground);
+ callout_widget->SetContentsView(content_view);
+ return callout_widget;
}
} // namespace internal
diff --git a/ash/wm/panel_layout_manager.h b/ash/wm/panel_layout_manager.h
index 9c94fef..ec032a1 100644
--- a/ash/wm/panel_layout_manager.h
+++ b/ash/wm/panel_layout_manager.h
@@ -91,7 +91,25 @@ class ASH_EXPORT PanelLayoutManager
friend class PanelLayoutManagerTest;
friend class PanelWindowResizerTest;
- typedef std::list<aura::Window*> PanelList;
+ views::Widget* CreateCalloutWidget();
+
+ struct PanelInfo{
+ PanelInfo() : window(NULL), callout_widget(NULL) {}
+
+ bool operator==(const aura::Window* other_window) const {
+ return window == other_window;
+ }
+
+ // A weak pointer to the panel window.
+ aura::Window* window;
+ // The callout widget for this panel. This pointer must be managed
+ // manually as this structure is used in a std::list. See
+ // http://www.chromium.org/developers/smart-pointer-guidelines
+ views::Widget* callout_widget;
+
+ };
+
+ typedef std::list<PanelInfo> PanelList;
void MinimizePanel(aura::Window* panel);
void RestorePanel(aura::Window* panel);
@@ -103,20 +121,8 @@ class ASH_EXPORT PanelLayoutManager
// changes or a panel is moved).
void UpdateStacking(aura::Window* active_panel);
- // Trigger a delayed task to update the callout. We use this because
- // otherwise, ShadowController::OnWindowPropertyChanged may be invoked after
- // we've already updated the callout, causing the drop shadow to be stacked on
- // top of the callout rather than the other way around.
- // TODO(dcheng): Possibly a bug in the shadow controller. If a window is
- // focused but not stacked at the top, I don't think its shadow should be
- // drawn on top of "higher" windows.
- void UpdateCallout(aura::Window* active_window);
-
- // Don't call this directly. Only UpdateCallout() should call this method.
- void ShowCalloutHelper(aura::Window* active_panel);
-
- // For testing.
- views::Widget* callout_widget() const { return callout_widget_.get(); }
+ // Update the callout arrows for all managed panels.
+ void UpdateCallouts();
// Parent window associated with this layout manager.
aura::Window* panel_container_;
@@ -131,8 +137,6 @@ class ASH_EXPORT PanelLayoutManager
// The last active panel. Used to maintain stacking even if no panels are
// currently focused.
aura::Window* last_active_panel_;
- // Manage the callout for the focused panel, if any.
- scoped_ptr<views::Widget> callout_widget_;
base::WeakPtrFactory<PanelLayoutManager> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(PanelLayoutManager);
diff --git a/ash/wm/panel_layout_manager_unittest.cc b/ash/wm/panel_layout_manager_unittest.cc
index 9a3c218..48170f7 100644
--- a/ash/wm/panel_layout_manager_unittest.cc
+++ b/ash/wm/panel_layout_manager_unittest.cc
@@ -72,12 +72,16 @@ class PanelLayoutManagerTest : public test::AshTestBase {
internal::kShellWindowId_PanelContainer);
}
- void GetCalloutWidget(views::Widget** widget) {
+ void GetCalloutWidgetForPanel(aura::Window* panel, views::Widget** widget) {
PanelLayoutManager* manager =
static_cast<PanelLayoutManager*>(GetPanelContainer()->layout_manager());
- ASSERT_TRUE(manager);
- ASSERT_TRUE(manager->callout_widget());
- *widget = manager->callout_widget();
+ DCHECK(manager);
+ PanelLayoutManager::PanelList::iterator found = std::find(
+ manager->panel_windows_.begin(), manager->panel_windows_.end(),
+ panel);
+ DCHECK(found != manager->panel_windows_.end());
+ DCHECK(found->callout_widget);
+ *widget = found->callout_widget;
}
void PanelInScreen(aura::Window* panel) {
@@ -127,7 +131,7 @@ class PanelLayoutManagerTest : public test::AshTestBase {
// Flush the message loop, since callout updates use a delayed task.
MessageLoop::current()->RunUntilIdle();
views::Widget* widget = NULL;
- GetCalloutWidget(&widget);
+ GetCalloutWidgetForPanel(panel, &widget);
Launcher* launcher = Launcher::ForPrimaryDisplay();
gfx::Rect icon_bounds = launcher->GetScreenBoundsOfItemIconForWindow(panel);
@@ -141,9 +145,9 @@ class PanelLayoutManagerTest : public test::AshTestBase {
1);
}
- bool IsCalloutVisible() {
+ bool IsPanelCalloutVisible(aura::Window* panel) {
views::Widget* widget = NULL;
- GetCalloutWidget(&widget);
+ GetCalloutWidgetForPanel(panel, &widget);
return widget->IsVisible();
}
@@ -238,7 +242,10 @@ TEST_F(PanelLayoutManagerTest, MultiplePanelCallout) {
scoped_ptr<aura::Window> w2(CreatePanelWindow(bounds));
scoped_ptr<aura::Window> w3(CreatePanelWindow(bounds));
scoped_ptr<aura::Window> w4(CreateNormalWindow());
- EXPECT_FALSE(IsCalloutVisible());
+ launcher_view_test()->RunMessageLoopUntilAnimationsDone();
+ EXPECT_TRUE(IsPanelCalloutVisible(w1.get()));
+ EXPECT_TRUE(IsPanelCalloutVisible(w2.get()));
+ EXPECT_TRUE(IsPanelCalloutVisible(w3.get()));
wm::ActivateWindow(w1.get());
EXPECT_NO_FATAL_FAILURE(IsCalloutAboveLauncherIcon(w1.get()));
wm::ActivateWindow(w2.get());
@@ -246,14 +253,11 @@ TEST_F(PanelLayoutManagerTest, MultiplePanelCallout) {
wm::ActivateWindow(w3.get());
EXPECT_NO_FATAL_FAILURE(IsCalloutAboveLauncherIcon(w3.get()));
wm::ActivateWindow(w4.get());
- EXPECT_FALSE(IsCalloutVisible());
wm::ActivateWindow(w3.get());
EXPECT_NO_FATAL_FAILURE(IsCalloutAboveLauncherIcon(w3.get()));
w3.reset();
if (views::corewm::UseFocusController())
EXPECT_NO_FATAL_FAILURE(IsCalloutAboveLauncherIcon(w2.get()));
- else
- EXPECT_FALSE(IsCalloutVisible());
}
// Tests removing panels.
@@ -359,20 +363,20 @@ TEST_F(PanelLayoutManagerTest, MinimizeRestorePanel) {
// Activate the window, ensure callout is visible.
wm::ActivateWindow(window.get());
RunAllPendingInMessageLoop();
- EXPECT_TRUE(IsCalloutVisible());
+ EXPECT_TRUE(IsPanelCalloutVisible(window.get()));
// Minimize the panel, callout should be hidden.
window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
RunAllPendingInMessageLoop();
- EXPECT_FALSE(IsCalloutVisible());
- // Restore the pantel; panel should not be activated by default and callout
- // should be hidden.
+ EXPECT_FALSE(IsPanelCalloutVisible(window.get()));
+ // Restore the pantel; panel should not be activated by default but callout
+ // should be visible.
window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
RunAllPendingInMessageLoop();
- EXPECT_FALSE(IsCalloutVisible());
+ EXPECT_TRUE(IsPanelCalloutVisible(window.get()));
// Activate the window, ensure callout is visible.
wm::ActivateWindow(window.get());
RunAllPendingInMessageLoop();
- EXPECT_TRUE(IsCalloutVisible());
+ EXPECT_TRUE(IsPanelCalloutVisible(window.get()));
}
TEST_F(PanelLayoutManagerTest, PanelMoveBetweenMultipleDisplays) {