diff options
-rw-r--r-- | ash/wm/workspace/managed_workspace.h | 2 | ||||
-rw-r--r-- | ui/aura/test/test_windows.cc | 12 | ||||
-rw-r--r-- | ui/aura/test/test_windows.h | 8 | ||||
-rw-r--r-- | ui/aura/window.cc | 85 | ||||
-rw-r--r-- | ui/aura/window.h | 23 | ||||
-rw-r--r-- | ui/aura/window_unittest.cc | 45 | ||||
-rw-r--r-- | ui/views/widget/native_widget_aura.cc | 5 | ||||
-rw-r--r-- | ui/views/widget/native_widget_aura.h | 1 | ||||
-rw-r--r-- | ui/views/widget/native_widget_gtk.cc | 4 | ||||
-rw-r--r-- | ui/views/widget/native_widget_gtk.h | 1 | ||||
-rw-r--r-- | ui/views/widget/native_widget_private.h | 1 | ||||
-rw-r--r-- | ui/views/widget/native_widget_win.cc | 4 | ||||
-rw-r--r-- | ui/views/widget/native_widget_win.h | 1 | ||||
-rw-r--r-- | ui/views/widget/widget.cc | 4 | ||||
-rw-r--r-- | ui/views/widget/widget.h | 3 |
15 files changed, 154 insertions, 45 deletions
diff --git a/ash/wm/workspace/managed_workspace.h b/ash/wm/workspace/managed_workspace.h index bf167ee..3b77c12 100644 --- a/ash/wm/workspace/managed_workspace.h +++ b/ash/wm/workspace/managed_workspace.h @@ -33,4 +33,4 @@ class ASH_EXPORT ManagedWorkspace : public Workspace { } // namespace internal } // namespace ash -#endif // ASH_WM_WORKPSACE_MANAGED_WORKSPACE_H_ +#endif // ASH_WM_WORKSPACE_MANAGED_WORKSPACE_H_ diff --git a/ui/aura/test/test_windows.cc b/ui/aura/test/test_windows.cc index 14fd638..3f2390b 100644 --- a/ui/aura/test/test_windows.cc +++ b/ui/aura/test/test_windows.cc @@ -4,6 +4,7 @@ #include "ui/aura/test/test_windows.h" +#include "base/string_number_conversions.h" #include "ui/aura/window.h" #include "ui/gfx/compositor/layer.h" #include "ui/gfx/rect.h" @@ -84,5 +85,16 @@ bool LayerIsAbove(Window* upper, Window* lower) { return ObjectIsAbove<ui::Layer>(upper->layer(), lower->layer()); } +std::string ChildWindowIDsAsString(aura::Window* parent) { + std::string result; + for (Window::Windows::const_iterator i = parent->children().begin(); + i != parent->children().end(); ++i) { + if (!result.empty()) + result += " "; + result += base::IntToString((*i)->id()); + } + return result; +} + } // namespace test } // namespace aura diff --git a/ui/aura/test/test_windows.h b/ui/aura/test/test_windows.h index d0b782d..e0ca117 100644 --- a/ui/aura/test/test_windows.h +++ b/ui/aura/test/test_windows.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,6 +6,8 @@ #define UI_AURA_TEST_TEST_WINDOWS_H_ #pragma once +#include <string> + #include "base/compiler_specific.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/aura/client/window_types.h" @@ -41,6 +43,10 @@ bool WindowIsAbove(Window* upper, Window* lower); // stacking order. bool LayerIsAbove(Window* upper, Window* lower); +// Returns a string containing the id of each of the child windows (bottommost +// first) of |parent|. The format of the string is "id1 id2 id...". +std::string ChildWindowIDsAsString(aura::Window* parent); + } // namespace test } // namespace aura diff --git a/ui/aura/window.cc b/ui/aura/window.cc index facec39..71fedda 100644 --- a/ui/aura/window.cc +++ b/ui/aura/window.cc @@ -255,35 +255,11 @@ void Window::StackChildAtTop(Window* child) { } void Window::StackChildAbove(Window* child, Window* target) { - DCHECK_NE(child, target); - DCHECK(child); - DCHECK(target); - DCHECK_EQ(this, child->parent()); - DCHECK_EQ(this, target->parent()); - - const size_t target_i = - std::find(children_.begin(), children_.end(), target) - children_.begin(); - - // By convention we don't stack on top of windows with layers with NULL - // delegates. Walk backward to find a valid target window. - // See tests WindowTest.StackingMadrigal and StackOverClosingTransient - // for an explanation of this. - size_t final_target_i = target_i; - while (final_target_i > 0 && - children_[final_target_i]->layer()->delegate() == NULL) - --final_target_i; - Window* final_target = children_[final_target_i]; - - // If we couldn't find a valid target position, don't move anything. - if (final_target->layer()->delegate() == NULL) - return; - - // Don't try to stack a child above itself. - if (child == final_target) - return; + StackChildRelativeTo(child, target, STACK_ABOVE); +} - // Move the child and all its transients. - StackChildAboveImpl(child, final_target); +void Window::StackChildBelow(Window* child, Window* target) { + StackChildRelativeTo(child, target, STACK_BELOW); } void Window::AddChild(Window* child) { @@ -670,7 +646,43 @@ void Window::OnParentChanged() { WindowObserver, observers_, OnWindowParentChanged(this, parent_)); } -void Window::StackChildAboveImpl(Window* child, Window* target) { +void Window::StackChildRelativeTo(Window* child, + Window* target, + StackDirection direction) { + DCHECK_NE(child, target); + DCHECK(child); + DCHECK(target); + DCHECK_EQ(this, child->parent()); + DCHECK_EQ(this, target->parent()); + + const size_t target_i = + std::find(children_.begin(), children_.end(), target) - children_.begin(); + + // By convention we don't stack on top of windows with layers with NULL + // delegates. Walk backward to find a valid target window. + // See tests WindowTest.StackingMadrigal and StackOverClosingTransient + // for an explanation of this. + size_t final_target_i = target_i; + while (final_target_i > 0 && + children_[final_target_i]->layer()->delegate() == NULL) + --final_target_i; + Window* final_target = children_[final_target_i]; + + // If we couldn't find a valid target position, don't move anything. + if (final_target->layer()->delegate() == NULL) + return; + + // Don't try to stack a child above itself. + if (child == final_target) + return; + + // Move the child and all its transients. + StackChildRelativeToImpl(child, final_target, direction); +} + +void Window::StackChildRelativeToImpl(Window* child, + Window* target, + StackDirection direction) { DCHECK_NE(child, target); DCHECK(child); DCHECK(target); @@ -683,14 +695,21 @@ void Window::StackChildAboveImpl(Window* child, Window* target) { std::find(children_.begin(), children_.end(), target) - children_.begin(); // Don't move the child if it is already in the right place. - if (child_i == target_i + 1) + if ((direction == STACK_ABOVE && child_i == target_i + 1) || + (direction == STACK_BELOW && child_i + 1 == target_i)) return; - const size_t dest_i = child_i < target_i ? target_i : target_i + 1; + const size_t dest_i = + direction == STACK_ABOVE ? + (child_i < target_i ? target_i : target_i + 1) : + (child_i < target_i ? target_i - 1 : target_i); children_.erase(children_.begin() + child_i); children_.insert(children_.begin() + dest_i, child); - layer()->StackAbove(child->layer(), target->layer()); + if (direction == STACK_ABOVE) + layer()->StackAbove(child->layer(), target->layer()); + else + layer()->StackBelow(child->layer(), target->layer()); // Stack any transient children that share the same parent to be in front of // 'child'. @@ -699,7 +718,7 @@ void Window::StackChildAboveImpl(Window* child, Window* target) { it != child->transient_children_.end(); ++it) { Window* transient_child = *it; if (transient_child->parent_ == this) { - StackChildAboveImpl(transient_child, last_transient); + StackChildRelativeToImpl(transient_child, last_transient, STACK_ABOVE); last_transient = transient_child; } } diff --git a/ui/aura/window.h b/ui/aura/window.h index a3d59b4..ebd3f13 100644 --- a/ui/aura/window.h +++ b/ui/aura/window.h @@ -164,6 +164,10 @@ class AURA_EXPORT Window : public ui::LayerDelegate { // see WindowTest.StackingMadrigal for details. void StackChildAbove(Window* child, Window* target); + // Stacks |child| below |target|. Does nothing if |child| is already below + // |target|. + void StackChildBelow(Window* child, Window* target); + // Tree operations. // TODO(beng): Child windows are currently not owned by the hierarchy. We // should change this. @@ -321,6 +325,13 @@ class AURA_EXPORT Window : public ui::LayerDelegate { private: friend class LayoutManager; + + // Used when stacking windows. + enum StackDirection { + STACK_ABOVE, + STACK_BELOW + }; + // Called by the public {Set,Get,Clear}Property functions. intptr_t SetPropertyInternal(const void* key, const char* name, @@ -352,8 +363,16 @@ class AURA_EXPORT Window : public ui::LayerDelegate { // Called when this window's parent has changed. void OnParentChanged(); - // Stacks |child| above |target| without checking for NULL layer delegates. - void StackChildAboveImpl(Window* child, Window* target); + // Determines the real location for stacking |child| and invokes + // StackChildRelativeToImpl(). + void StackChildRelativeTo(Window* child, + Window* target, + StackDirection direction); + + // Implementation of StackChildRelativeTo(). + void StackChildRelativeToImpl(Window* child, + Window* target, + StackDirection direction); // Called when this window's stacking order among its siblings is changed. void OnStackingChanged(); diff --git a/ui/aura/window_unittest.cc b/ui/aura/window_unittest.cc index f491663..5a17664 100644 --- a/ui/aura/window_unittest.cc +++ b/ui/aura/window_unittest.cc @@ -428,6 +428,38 @@ TEST_F(WindowTest, StackChildAtTop) { EXPECT_EQ(child2.layer(), parent.layer()->children()[0]); } +// Make sure StackChildBelow works. +TEST_F(WindowTest, StackChildBelow) { + Window parent(NULL); + parent.Init(ui::Layer::LAYER_NOT_DRAWN); + Window child1(NULL); + child1.Init(ui::Layer::LAYER_NOT_DRAWN); + child1.set_id(1); + Window child2(NULL); + child2.Init(ui::Layer::LAYER_NOT_DRAWN); + child2.set_id(2); + Window child3(NULL); + child3.Init(ui::Layer::LAYER_NOT_DRAWN); + child3.set_id(3); + + child1.SetParent(&parent); + child2.SetParent(&parent); + child3.SetParent(&parent); + EXPECT_EQ("1 2 3", ChildWindowIDsAsString(&parent)); + + parent.StackChildBelow(&child1, &child2); + EXPECT_EQ("1 2 3", ChildWindowIDsAsString(&parent)); + + parent.StackChildBelow(&child2, &child1); + EXPECT_EQ("2 1 3", ChildWindowIDsAsString(&parent)); + + parent.StackChildBelow(&child3, &child2); + EXPECT_EQ("3 2 1", ChildWindowIDsAsString(&parent)); + + parent.StackChildBelow(&child3, &child1); + EXPECT_EQ("2 3 1", ChildWindowIDsAsString(&parent)); +} + // Various assertions for StackChildAbove. TEST_F(WindowTest, StackChildAbove) { Window parent(NULL); @@ -1306,6 +1338,8 @@ TEST_F(WindowTest, StackWindowsWhoseLayersHaveNoDelegate) { } TEST_F(WindowTest, StackTransientsWhoseLayersHaveNoDelegate) { + RootWindow* root = root_window(); + // Create a window with several transients, then a couple windows on top. scoped_ptr<Window> window1(CreateTestWindowWithId(1, NULL)); scoped_ptr<Window> window11(CreateTransientChild(11, window1.get())); @@ -1314,6 +1348,8 @@ TEST_F(WindowTest, StackTransientsWhoseLayersHaveNoDelegate) { scoped_ptr<Window> window2(CreateTestWindowWithId(2, NULL)); scoped_ptr<Window> window3(CreateTestWindowWithId(3, NULL)); + EXPECT_EQ("1 11 12 13 2 3", ChildWindowIDsAsString(root)); + // Remove the delegates of a couple of transients, as if they are closing // and animating out. window11->layer()->set_delegate(NULL); @@ -1321,16 +1357,9 @@ TEST_F(WindowTest, StackTransientsWhoseLayersHaveNoDelegate) { // Move window1 to the front. All transients should move with it, and their // order should be preserved. - RootWindow* root = root_window(); root->StackChildAtTop(window1.get()); - ASSERT_EQ(6u, root->children().size()); - EXPECT_EQ(window2.get(), root->children()[0]); - EXPECT_EQ(window3.get(), root->children()[1]); - EXPECT_EQ(window1.get(), root->children()[2]); - EXPECT_EQ(window11.get(), root->children()[3]); - EXPECT_EQ(window12.get(), root->children()[4]); - EXPECT_EQ(window13.get(), root->children()[5]); + EXPECT_EQ("2 3 1 11 12 13", ChildWindowIDsAsString(root)); } class TestVisibilityClient : public client::VisibilityClient { diff --git a/ui/views/widget/native_widget_aura.cc b/ui/views/widget/native_widget_aura.cc index 9e0cefc..63bbe91 100644 --- a/ui/views/widget/native_widget_aura.cc +++ b/ui/views/widget/native_widget_aura.cc @@ -424,6 +424,11 @@ void NativeWidgetAura::StackAtTop() { window_->parent()->StackChildAtTop(window_); } +void NativeWidgetAura::StackBelow(gfx::NativeView native_view) { + if (window_->parent() && window_->parent() == native_view->parent()) + window_->parent()->StackChildBelow(window_, native_view); +} + void NativeWidgetAura::SetShape(gfx::NativeRegion region) { // No need for this. Just delete and ignore. delete region; diff --git a/ui/views/widget/native_widget_aura.h b/ui/views/widget/native_widget_aura.h index c8f27a9..7382e0a 100644 --- a/ui/views/widget/native_widget_aura.h +++ b/ui/views/widget/native_widget_aura.h @@ -85,6 +85,7 @@ class VIEWS_EXPORT NativeWidgetAura : public internal::NativeWidgetPrivate, virtual void SetSize(const gfx::Size& size) OVERRIDE; virtual void StackAbove(gfx::NativeView native_view) OVERRIDE; virtual void StackAtTop() OVERRIDE; + virtual void StackBelow(gfx::NativeView native_view) OVERRIDE; virtual void SetShape(gfx::NativeRegion shape) OVERRIDE; virtual void Close() OVERRIDE; virtual void CloseNow() OVERRIDE; diff --git a/ui/views/widget/native_widget_gtk.cc b/ui/views/widget/native_widget_gtk.cc index f1948de..975f19e 100644 --- a/ui/views/widget/native_widget_gtk.cc +++ b/ui/views/widget/native_widget_gtk.cc @@ -1064,6 +1064,10 @@ void NativeWidgetGtk::StackAtTop() { gtk_window_present(GTK_WINDOW(GetNativeView())); } +void NativeWidgetGtk::StackBelow(gfx::NativeView native_view) { + NOTIMPLEMENTED(); +} + void NativeWidgetGtk::SetShape(gfx::NativeRegion region) { if (widget_ && widget_->window) { gdk_window_shape_combine_region(widget_->window, region, 0, 0); diff --git a/ui/views/widget/native_widget_gtk.h b/ui/views/widget/native_widget_gtk.h index 4d7a44c..92ef99c 100644 --- a/ui/views/widget/native_widget_gtk.h +++ b/ui/views/widget/native_widget_gtk.h @@ -187,6 +187,7 @@ class VIEWS_EXPORT NativeWidgetGtk : public internal::NativeWidgetPrivate, virtual void SetSize(const gfx::Size& size) OVERRIDE; virtual void StackAbove(gfx::NativeView native_view) OVERRIDE; virtual void StackAtTop() OVERRIDE; + virtual void StackBelow(gfx::NativeView native_view) OVERRIDE; virtual void SetShape(gfx::NativeRegion shape) OVERRIDE; virtual void Close() OVERRIDE; virtual void CloseNow() OVERRIDE; diff --git a/ui/views/widget/native_widget_private.h b/ui/views/widget/native_widget_private.h index f81cf78..6129945 100644 --- a/ui/views/widget/native_widget_private.h +++ b/ui/views/widget/native_widget_private.h @@ -171,6 +171,7 @@ class VIEWS_EXPORT NativeWidgetPrivate : public NativeWidget, virtual void SetSize(const gfx::Size& size) = 0; virtual void StackAbove(gfx::NativeView native_view) = 0; virtual void StackAtTop() = 0; + virtual void StackBelow(gfx::NativeView native_view) = 0; virtual void SetShape(gfx::NativeRegion shape) = 0; virtual void Close() = 0; virtual void CloseNow() = 0; diff --git a/ui/views/widget/native_widget_win.cc b/ui/views/widget/native_widget_win.cc index 5f61811..a3b7c28 100644 --- a/ui/views/widget/native_widget_win.cc +++ b/ui/views/widget/native_widget_win.cc @@ -825,6 +825,10 @@ void NativeWidgetWin::StackAtTop() { SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE); } +void NativeWidgetWin::StackBelow(gfx::NativeView native_view) { + NOTIMPLEMENTED(); +} + void NativeWidgetWin::SetShape(gfx::NativeRegion region) { SetWindowRgn(region, TRUE); } diff --git a/ui/views/widget/native_widget_win.h b/ui/views/widget/native_widget_win.h index a3537c7..6b6fea1 100644 --- a/ui/views/widget/native_widget_win.h +++ b/ui/views/widget/native_widget_win.h @@ -216,6 +216,7 @@ class VIEWS_EXPORT NativeWidgetWin : public ui::WindowImpl, virtual void SetSize(const gfx::Size& size) OVERRIDE; virtual void StackAbove(gfx::NativeView native_view) OVERRIDE; virtual void StackAtTop() OVERRIDE; + virtual void StackBelow(gfx::NativeView native_view) OVERRIDE; virtual void SetShape(gfx::NativeRegion shape) OVERRIDE; virtual void Close() OVERRIDE; virtual void CloseNow() OVERRIDE; diff --git a/ui/views/widget/widget.cc b/ui/views/widget/widget.cc index 6a2fdc9..569fd92 100644 --- a/ui/views/widget/widget.cc +++ b/ui/views/widget/widget.cc @@ -485,6 +485,10 @@ void Widget::StackAtTop() { native_widget_->StackAtTop(); } +void Widget::StackBelow(gfx::NativeView native_view) { + native_widget_->StackBelow(native_view); +} + void Widget::SetShape(gfx::NativeRegion shape) { native_widget_->SetShape(shape); } diff --git a/ui/views/widget/widget.h b/ui/views/widget/widget.h index c242cf3..baf7837 100644 --- a/ui/views/widget/widget.h +++ b/ui/views/widget/widget.h @@ -337,6 +337,9 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate, void StackAbove(gfx::NativeView native_view); void StackAtTop(); + // Places the widget below the specified NativeView. + void StackBelow(gfx::NativeView native_view); + // Sets a shape on the widget. This takes ownership of shape. void SetShape(gfx::NativeRegion shape); |