diff options
34 files changed, 928 insertions, 759 deletions
diff --git a/ui/aura/aura.gyp b/ui/aura/aura.gyp index 144069c..96712f4 100644 --- a/ui/aura/aura.gyp +++ b/ui/aura/aura.gyp @@ -44,8 +44,6 @@ 'layout_manager.h', 'screen_aura.cc', 'screen_aura.h', - 'toplevel_window_container.cc', - 'toplevel_window_container.h', 'window.cc', 'window.h', 'window_delegate.h', @@ -73,6 +71,8 @@ 'test/event_generator.h', 'test/test_stacking_client.cc', 'test/test_stacking_client.h', + 'test/test_windows.cc', + 'test/test_windows.h', 'test/test_window_delegate.cc', 'test/test_window_delegate.h', ], @@ -126,7 +126,6 @@ 'test/run_all_unittests.cc', 'test/test_suite.cc', 'test/test_suite.h', - 'desktop_unittest.cc', 'event_filter_unittest.cc', 'window_unittest.cc', '<(SHARED_INTERMEDIATE_DIR)/ui/gfx/gfx_resources.rc', diff --git a/ui/aura/client/stacking_client.h b/ui/aura/client/stacking_client.h index c56e319..26d137b 100644 --- a/ui/aura/client/stacking_client.h +++ b/ui/aura/client/stacking_client.h @@ -22,6 +22,11 @@ class AURA_EXPORT StackingClient { // of its choosing. virtual void AddChildToDefaultParent(Window* window) = 0; + // Returns true if |window| can be activated or deactivated. + // A window manager typically defines some notion of "top level window" that + // supports activation/deactivation. + virtual bool CanActivateWindow(Window* window) const = 0; + // Returns the window that should be activated other than |ignore|. virtual Window* GetTopmostWindowToActivate(Window* ignore) const = 0; }; diff --git a/ui/aura/desktop.cc b/ui/aura/desktop.cc index dd5cf98..d08a062 100644 --- a/ui/aura/desktop.cc +++ b/ui/aura/desktop.cc @@ -21,7 +21,6 @@ #include "ui/aura/event_filter.h" #include "ui/aura/focus_manager.h" #include "ui/aura/screen_aura.h" -#include "ui/aura/toplevel_window_container.h" #include "ui/aura/window.h" #include "ui/aura/window_delegate.h" #include "ui/base/hit_test.h" @@ -45,30 +44,6 @@ static const int kDefaultHostWindowY = 200; static const int kDefaultHostWindowWidth = 1280; static const int kDefaultHostWindowHeight = 1024; -// Returns the default cursor for a window component. -gfx::NativeCursor CursorForWindowComponent(int window_component) { - switch (window_component) { - case HTBOTTOM: - return aura::kCursorSouthResize; - case HTBOTTOMLEFT: - return aura::kCursorSouthWestResize; - case HTBOTTOMRIGHT: - return aura::kCursorSouthEastResize; - case HTLEFT: - return aura::kCursorWestResize; - case HTRIGHT: - return aura::kCursorEastResize; - case HTTOP: - return aura::kCursorNorthResize; - case HTTOPLEFT: - return aura::kCursorNorthWestResize; - case HTTOPRIGHT: - return aura::kCursorNorthEastResize; - default: - return aura::kCursorNull; - } -} - bool IsNonClientLocation(Window* target, const gfx::Point& location) { if (!target->delegate()) return false; @@ -82,10 +57,14 @@ class DefaultStackingClient : public StackingClient { virtual ~DefaultStackingClient() {} private: + + // Overridden from StackingClient: virtual void AddChildToDefaultParent(Window* window) OVERRIDE { desktop_->AddChild(window); } - + virtual bool CanActivateWindow(Window* window) const OVERRIDE { + return window->parent() == desktop_; + } virtual Window* GetTopmostWindowToActivate(Window* ignore) const OVERRIDE { Window::Windows::const_reverse_iterator i; for (i = desktop_->children().rbegin(); @@ -103,79 +82,6 @@ class DefaultStackingClient : public StackingClient { DISALLOW_COPY_AND_ASSIGN(DefaultStackingClient); }; -class DesktopEventFilter : public EventFilter { - public: - explicit DesktopEventFilter(Window* owner) : EventFilter(owner) {} - virtual ~DesktopEventFilter() {} - - // Overridden from EventFilter: - virtual bool PreHandleKeyEvent(Window* target, KeyEvent* event) OVERRIDE { - return false; - } - virtual bool PreHandleMouseEvent(Window* target, MouseEvent* event) OVERRIDE { - switch (event->type()) { - case ui::ET_MOUSE_PRESSED: - ActivateIfNecessary(target, event); - break; - case ui::ET_MOUSE_MOVED: - HandleMouseMoved(target, event); - break; - default: - break; - } - return false; - } - virtual ui::TouchStatus PreHandleTouchEvent(Window* target, - TouchEvent* event) OVERRIDE { - if (event->type() == ui::ET_TOUCH_PRESSED) - ActivateIfNecessary(target, event); - return ui::TOUCH_STATUS_UNKNOWN; - } - - private: - // If necessary, activates |window| and changes focus. - void ActivateIfNecessary(Window* window, Event* event) { - // TODO(beng): some windows (e.g. disabled ones, tooltips, etc) may not be - // focusable. - - Window* active_window = Desktop::GetInstance()->active_window(); - Window* toplevel_window = window; - while (toplevel_window && toplevel_window != active_window && - toplevel_window->parent() && - !toplevel_window->parent()->AsToplevelWindowContainer()) { - toplevel_window = toplevel_window->parent(); - } - if (toplevel_window == active_window) { - // |window| is a descendant of the active window, no need to activate. - window->GetFocusManager()->SetFocusedWindow(window); - return; - } - if (!toplevel_window) { - // |window| is not in a top level window. - return; - } - if (!toplevel_window->delegate() || - !toplevel_window->delegate()->ShouldActivate(event)) - return; - - Desktop::GetInstance()->SetActiveWindow(toplevel_window, window); - } - - // Updates the cursor if the target provides a custom one, and provides - // default resize cursors for window edges. - void HandleMouseMoved(Window* target, MouseEvent* event) { - gfx::NativeCursor cursor = target->GetCursor(event->location()); - if (event->flags() & ui::EF_IS_NON_CLIENT) { - int window_component = - target->delegate()->GetNonClientComponent(event->location()); - cursor = CursorForWindowComponent(window_component); - } - Desktop::GetInstance()->SetCursor(cursor); - } - - DISALLOW_COPY_AND_ASSIGN(DesktopEventFilter); -}; - typedef std::vector<EventFilter*> EventFilters; void GetEventFiltersToNotify(Window* target, EventFilters* filters) { @@ -255,7 +161,6 @@ Desktop::Desktop() gfx::Screen::SetInstance(screen_); host_->SetDesktop(this); last_mouse_location_ = host_->QueryMouseLocation(); - SetEventFilter(new DesktopEventFilter(this)); if (ui::Compositor::compositor_factory()) { compositor_ = (*ui::Compositor::compositor_factory())(this); @@ -406,14 +311,17 @@ void Desktop::OnHostResized(const gfx::Size& size) { } void Desktop::SetActiveWindow(Window* window, Window* to_focus) { - // We only allow top level windows to be active. - if (window && window != window->GetToplevelWindow()) { - // Ignore requests to activate windows that aren't in a top level window. + // The stacking client may impose rules on what window configurations can be + // activated or deactivated. + if (window && !stacking_client_->CanActivateWindow(window)) return; - } - + // The window may not be activate-able. + if (window && !window->CanActivate()) + return; + // Nothing may actually have changed. if (active_window_ == window) return; + Window* old_active = active_window_; active_window_ = window; // Invoke OnLostActive after we've changed the active window. That way if the @@ -437,18 +345,14 @@ void Desktop::ActivateTopmostWindow() { } void Desktop::Deactivate(Window* window) { - if (!window) + // The stacking client may impose rules on what window configurations can be + // activated or deactivated. + if (!window || !stacking_client_->CanActivateWindow(window)) + return; + if (active_window_ != window) return; - Window* toplevel_ancestor = window->GetToplevelWindow(); - if (!toplevel_ancestor || toplevel_ancestor != window) - return; // Not a top level window. - - if (active_window() != toplevel_ancestor) - return; // Top level ancestor is already not active. - - Window* to_activate = - stacking_client_->GetTopmostWindowToActivate(toplevel_ancestor); + Window* to_activate = stacking_client_->GetTopmostWindowToActivate(window); if (to_activate) SetActiveWindow(to_activate, NULL); } diff --git a/ui/aura/desktop.h b/ui/aura/desktop.h index 6089331..5f455ff 100644 --- a/ui/aura/desktop.h +++ b/ui/aura/desktop.h @@ -97,6 +97,7 @@ class AURA_EXPORT Desktop : public ui::CompositorDelegate, // Sets the active window to |window| and the focused window to |to_focus|. // If |to_focus| is NULL, |window| is focused. + // |window| can be NULL. void SetActiveWindow(Window* window, Window* to_focus); // Activates the topmost window. Does nothing if the topmost window is already diff --git a/ui/aura/desktop_unittest.cc b/ui/aura/desktop_unittest.cc deleted file mode 100644 index d6ac2ed..0000000 --- a/ui/aura/desktop_unittest.cc +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright (c) 2011 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. - -#include "ui/aura/desktop.h" - -#include "ui/aura/event.h" -#include "ui/aura/test/aura_test_base.h" -#include "ui/aura/test/test_window_delegate.h" -#include "ui/base/events.h" -#include "ui/base/hit_test.h" -#include "ui/gfx/point.h" - -namespace aura { -namespace test { - -namespace { - -Window* CreateTestWindowWithDelegate(WindowDelegate* delegate, - const gfx::Rect& bounds, - Window* parent) { - Window* window = new Window(delegate); - window->Init(ui::Layer::LAYER_HAS_TEXTURE); - window->SetBounds(bounds); - window->Show(); - window->SetParent(parent); - return window; -} - -class HitTestWindowDelegate : public TestWindowDelegate { - public: - HitTestWindowDelegate() - : hittest_code_(HTNOWHERE) { - } - virtual ~HitTestWindowDelegate() {} - void set_hittest_code(int hittest_code) { hittest_code_ = hittest_code; } - - private: - // Overridden from TestWindowDelegate: - virtual int GetNonClientComponent(const gfx::Point& point) const OVERRIDE { - return hittest_code_; - } - - int hittest_code_; - - DISALLOW_COPY_AND_ASSIGN(HitTestWindowDelegate); -}; - -} // namespace - -class DesktopTest : public AuraTestBase { - public: - DesktopTest() {} - virtual ~DesktopTest() {} - - private: - DISALLOW_COPY_AND_ASSIGN(DesktopTest); -}; - -TEST_F(DesktopTest, MouseEventCursors) { - Desktop* desktop = Desktop::GetInstance(); - - // Create a window. - const int kWindowLeft = 123; - const int kWindowTop = 45; - HitTestWindowDelegate window_delegate; - scoped_ptr<Window> window(CreateTestWindowWithDelegate( - &window_delegate, - gfx::Rect(kWindowLeft, kWindowTop, 640, 480), - NULL)); - - // Create two mouse movement events we can switch between. - gfx::Point point1(kWindowLeft, kWindowTop); - Window::ConvertPointToWindow(window->parent(), desktop, &point1); - MouseEvent move1(ui::ET_MOUSE_MOVED, point1, 0x0); - - gfx::Point point2(kWindowLeft + 1, kWindowTop + 1); - Window::ConvertPointToWindow(window->parent(), desktop, &point2); - MouseEvent move2(ui::ET_MOUSE_MOVED, point2, 0x0); - - // Cursor starts as null. - EXPECT_EQ(kCursorNull, desktop->last_cursor()); - - // Resize edges and corners show proper cursors. - window_delegate.set_hittest_code(HTBOTTOM); - desktop->DispatchMouseEvent(&move1); - EXPECT_EQ(kCursorSouthResize, desktop->last_cursor()); - - window_delegate.set_hittest_code(HTBOTTOMLEFT); - desktop->DispatchMouseEvent(&move2); - EXPECT_EQ(kCursorSouthWestResize, desktop->last_cursor()); - - window_delegate.set_hittest_code(HTBOTTOMRIGHT); - desktop->DispatchMouseEvent(&move1); - EXPECT_EQ(kCursorSouthEastResize, desktop->last_cursor()); - - window_delegate.set_hittest_code(HTLEFT); - desktop->DispatchMouseEvent(&move2); - EXPECT_EQ(kCursorWestResize, desktop->last_cursor()); - - window_delegate.set_hittest_code(HTRIGHT); - desktop->DispatchMouseEvent(&move1); - EXPECT_EQ(kCursorEastResize, desktop->last_cursor()); - - window_delegate.set_hittest_code(HTTOP); - desktop->DispatchMouseEvent(&move2); - EXPECT_EQ(kCursorNorthResize, desktop->last_cursor()); - - window_delegate.set_hittest_code(HTTOPLEFT); - desktop->DispatchMouseEvent(&move1); - EXPECT_EQ(kCursorNorthWestResize, desktop->last_cursor()); - - window_delegate.set_hittest_code(HTTOPRIGHT); - desktop->DispatchMouseEvent(&move2); - EXPECT_EQ(kCursorNorthEastResize, desktop->last_cursor()); - - // Client area uses null cursor. - window_delegate.set_hittest_code(HTCLIENT); - desktop->DispatchMouseEvent(&move1); - EXPECT_EQ(kCursorNull, desktop->last_cursor()); -} - -} // namespace test -} // namespace aura diff --git a/ui/aura/test/test_stacking_client.cc b/ui/aura/test/test_stacking_client.cc index 37ce262..3191a84 100644 --- a/ui/aura/test/test_stacking_client.cc +++ b/ui/aura/test/test_stacking_client.cc @@ -10,7 +10,7 @@ namespace aura { namespace test { TestStackingClient::TestStackingClient() - : default_container_(new ToplevelWindowContainer) { + : default_container_(new Window(NULL)) { Desktop::GetInstance()->SetStackingClient(this); default_container_->Init(ui::Layer::LAYER_HAS_NO_TEXTURE); default_container_->SetBounds( @@ -26,8 +26,19 @@ void TestStackingClient::AddChildToDefaultParent(Window* window) { default_container_->AddChild(window); } +bool TestStackingClient::CanActivateWindow(Window* window) const { + return window->parent() == default_container_; +} + Window* TestStackingClient::GetTopmostWindowToActivate(Window* ignore) const { - return default_container_->GetTopmostWindowToActivate(ignore); + for (aura::Window::Windows::const_reverse_iterator i = + default_container_->children().rbegin(); + i != default_container_->children().rend(); + ++i) { + if (*i != ignore && (*i)->CanActivate()) + return *i; + } + return NULL; } } // namespace test diff --git a/ui/aura/test/test_stacking_client.h b/ui/aura/test/test_stacking_client.h index bf77ff8..3ea0ba5 100644 --- a/ui/aura/test/test_stacking_client.h +++ b/ui/aura/test/test_stacking_client.h @@ -10,10 +10,9 @@ #include "base/compiler_specific.h" #include "base/memory/scoped_ptr.h" #include "ui/aura/client/stacking_client.h" -#include "ui/aura/toplevel_window_container.h" namespace aura { -class ToplevelWindowContainer; +class Window; namespace test { @@ -30,9 +29,10 @@ class TestStackingClient : public StackingClient { private: // Overridden from StackingClient: virtual void AddChildToDefaultParent(Window* window) OVERRIDE; + virtual bool CanActivateWindow(Window* window) const OVERRIDE; virtual Window* GetTopmostWindowToActivate(Window* ignore) const OVERRIDE; - scoped_ptr<ToplevelWindowContainer> default_container_; + scoped_ptr<Window> default_container_; DISALLOW_COPY_AND_ASSIGN(TestStackingClient); }; diff --git a/ui/aura/test/test_window_delegate.cc b/ui/aura/test/test_window_delegate.cc index 8957eba..b179fda 100644 --- a/ui/aura/test/test_window_delegate.cc +++ b/ui/aura/test/test_window_delegate.cc @@ -4,11 +4,18 @@ #include "ui/aura/test/test_window_delegate.h" +#include "third_party/skia/include/core/SkCanvas.h" +#include "ui/aura/event.h" +#include "ui/aura/window.h" #include "ui/base/hit_test.h" +#include "ui/gfx/canvas.h" namespace aura { namespace test { +//////////////////////////////////////////////////////////////////////////////// +// TestWindowDelegate + TestWindowDelegate::TestWindowDelegate() { } @@ -70,5 +77,55 @@ void TestWindowDelegate::OnWindowDestroyed() { void TestWindowDelegate::OnWindowVisibilityChanged(bool visible) { } + +//////////////////////////////////////////////////////////////////////////////// +// ColorTestWindowDelegate + +ColorTestWindowDelegate::ColorTestWindowDelegate(SkColor color) + : color_(color), + last_key_code_(ui::VKEY_UNKNOWN) { +} +ColorTestWindowDelegate::~ColorTestWindowDelegate() { +} + +bool ColorTestWindowDelegate::OnKeyEvent(KeyEvent* event) { + last_key_code_ = event->key_code(); + return true; +} +void ColorTestWindowDelegate::OnWindowDestroyed() { + delete this; +} +void ColorTestWindowDelegate::OnPaint(gfx::Canvas* canvas) { + canvas->GetSkCanvas()->drawColor(color_, SkXfermode::kSrc_Mode); +} + +//////////////////////////////////////////////////////////////////////////////// +// ActivateWindowDelegate + +ActivateWindowDelegate::ActivateWindowDelegate() + : activate_(true), + activated_count_(0), + lost_active_count_(0), + should_activate_count_(0) { +} + +ActivateWindowDelegate::ActivateWindowDelegate(bool activate) + : activate_(activate), + activated_count_(0), + lost_active_count_(0), + should_activate_count_(0) { +} + +bool ActivateWindowDelegate::ShouldActivate(Event* event) { + should_activate_count_++; + return activate_; +} +void ActivateWindowDelegate::OnActivated() { + activated_count_++; +} +void ActivateWindowDelegate::OnLostActive() { + lost_active_count_++; +} + } // namespace test } // namespace aura diff --git a/ui/aura/test/test_window_delegate.h b/ui/aura/test/test_window_delegate.h index 4150f67..783402b 100644 --- a/ui/aura/test/test_window_delegate.h +++ b/ui/aura/test/test_window_delegate.h @@ -7,6 +7,7 @@ #pragma once #include "base/compiler_specific.h" +#include "third_party/skia/include/core/SkColor.h" #include "ui/aura/window_delegate.h" namespace aura { @@ -41,6 +42,54 @@ class TestWindowDelegate : public WindowDelegate { DISALLOW_COPY_AND_ASSIGN(TestWindowDelegate); }; +// A simple WindowDelegate implementation for these tests. It owns itself +// (deletes itself when the Window it is attached to is destroyed). +class ColorTestWindowDelegate : public TestWindowDelegate { + public: + explicit ColorTestWindowDelegate(SkColor color); + virtual ~ColorTestWindowDelegate(); + + ui::KeyboardCode last_key_code() const { return last_key_code_; } + + // Overridden from TestWindowDelegate: + virtual bool OnKeyEvent(KeyEvent* event) OVERRIDE; + virtual void OnWindowDestroyed() OVERRIDE; + virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE; + + private: + SkColor color_; + ui::KeyboardCode last_key_code_; + + DISALLOW_COPY_AND_ASSIGN(ColorTestWindowDelegate); +}; + +class ActivateWindowDelegate : public TestWindowDelegate { + public: + ActivateWindowDelegate(); + explicit ActivateWindowDelegate(bool activate); + + void set_activate(bool v) { activate_ = v; } + int activated_count() const { return activated_count_; } + int lost_active_count() const { return lost_active_count_; } + int should_activate_count() const { return should_activate_count_; } + void Clear() { + activated_count_ = lost_active_count_ = should_activate_count_ = 0; + } + + // Overridden from TestWindowDelegate: + virtual bool ShouldActivate(Event* event) OVERRIDE; + virtual void OnActivated() OVERRIDE; + virtual void OnLostActive() OVERRIDE; + + private: + bool activate_; + int activated_count_; + int lost_active_count_; + int should_activate_count_; + + DISALLOW_COPY_AND_ASSIGN(ActivateWindowDelegate); +}; + } // namespace test } // namespace aura diff --git a/ui/aura/test/test_windows.cc b/ui/aura/test/test_windows.cc new file mode 100644 index 0000000..5fe85f4 --- /dev/null +++ b/ui/aura/test/test_windows.cc @@ -0,0 +1,45 @@ +// Copyright (c) 2011 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. + +#include "ui/aura/test/test_windows.h" + +#include "ui/aura/window.h" +#include "ui/gfx/compositor/layer.h" +#include "ui/gfx/rect.h" + +namespace aura { +namespace test { + +Window* CreateTestWindowWithId(int id, Window* parent) { + return CreateTestWindowWithDelegate(NULL, id, gfx::Rect(), parent); +} + +Window* CreateTestWindowWithBounds(const gfx::Rect& bounds, Window* parent) { + return CreateTestWindowWithDelegate(NULL, 0, bounds, parent); +} + +Window* CreateTestWindow(SkColor color, + int id, + const gfx::Rect& bounds, + Window* parent) { + return CreateTestWindowWithDelegate(new ColorTestWindowDelegate(color), + id, bounds, parent); +} + +Window* CreateTestWindowWithDelegate(WindowDelegate* delegate, + int id, + const gfx::Rect& bounds, + Window* parent) { + Window* window = new Window(delegate); + window->set_id(id); + window->SetType(aura::WINDOW_TYPE_NORMAL); + window->Init(ui::Layer::LAYER_HAS_TEXTURE); + window->SetBounds(bounds); + window->Show(); + window->SetParent(parent); + return window; +} + +} // namespace test +} // namespace aura diff --git a/ui/aura/test/test_windows.h b/ui/aura/test/test_windows.h new file mode 100644 index 0000000..2edf133 --- /dev/null +++ b/ui/aura/test/test_windows.h @@ -0,0 +1,35 @@ +// Copyright (c) 2011 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. + +#ifndef UI_AURA_TEST_TEST_UTILS_H_ +#define UI_AURA_TEST_TEST_UTILS_H_ +#pragma once + +#include "base/compiler_specific.h" +#include "third_party/skia/include/core/SkColor.h" +#include "ui/aura/test/test_window_delegate.h" +#include "ui/aura/test/aura_test_base.h" + +namespace gfx { +class Canvas; +} + +namespace aura { +namespace test { + +Window* CreateTestWindowWithId(int id, Window* parent); +Window* CreateTestWindowWithBounds(const gfx::Rect& bounds, Window* parent); +Window* CreateTestWindow(SkColor color, + int id, + const gfx::Rect& bounds, + Window* parent); +Window* CreateTestWindowWithDelegate(WindowDelegate* delegate, + int id, + const gfx::Rect& bounds, + Window* parent); + +} // namespace test +} // namespace aura + +#endif // UI_AURA_TEST_TEST_UTILS_H_ diff --git a/ui/aura/toplevel_window_container.cc b/ui/aura/toplevel_window_container.cc deleted file mode 100644 index 9605d88..0000000 --- a/ui/aura/toplevel_window_container.cc +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) 2011 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. - -#include "ui/aura/toplevel_window_container.h" - -#include "base/utf_string_conversions.h" - -namespace aura { - -ToplevelWindowContainer::ToplevelWindowContainer() - : Window(NULL) { - set_name("ToplevelWindowContainer"); -} - -ToplevelWindowContainer::~ToplevelWindowContainer() { -} - -Window* ToplevelWindowContainer::GetTopmostWindowToActivate( - Window* ignore) const { - for (Window::Windows::const_reverse_iterator i = children().rbegin(); - i != children().rend(); ++i) { - if (*i != ignore && (*i)->CanActivate()) - return *i; - } - return NULL; -} - -ToplevelWindowContainer* ToplevelWindowContainer::AsToplevelWindowContainer() { - return this; -} - -const ToplevelWindowContainer* - ToplevelWindowContainer::AsToplevelWindowContainer() const { - return this; -} -} // namespace aura diff --git a/ui/aura/toplevel_window_container.h b/ui/aura/toplevel_window_container.h deleted file mode 100644 index 67c537a..0000000 --- a/ui/aura/toplevel_window_container.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2011 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. - -#ifndef UI_AURA_TOPLEVEL_WINDOW_CONTAINER_H_ -#define UI_AURA_TOPLEVEL_WINDOW_CONTAINER_H_ -#pragma once - -#include "ui/aura/window.h" -#include "ui/aura/aura_export.h" - -namespace aura { - -// A Window subclass that groups top-level windows. -class AURA_EXPORT ToplevelWindowContainer : public Window { - public: - ToplevelWindowContainer(); - virtual ~ToplevelWindowContainer(); - - // Returns the topmost window to activate, ignoring |ignore|. - Window* GetTopmostWindowToActivate(Window* ignore) const; - - // Overridden from Window: - virtual ToplevelWindowContainer* AsToplevelWindowContainer() OVERRIDE; - virtual const ToplevelWindowContainer* - AsToplevelWindowContainer() const OVERRIDE; - - private: - DISALLOW_COPY_AND_ASSIGN(ToplevelWindowContainer); -}; - -} // namespace aura - -#endif // UI_AURA_TOPLEVEL_WINDOW_CONTAINER_H_ diff --git a/ui/aura/window.cc b/ui/aura/window.cc index 49be6e9..d1caa04 100644 --- a/ui/aura/window.cc +++ b/ui/aura/window.cc @@ -120,14 +120,6 @@ bool Window::IsActive() const { return aura::Desktop::GetInstance()->active_window() == this; } -ToplevelWindowContainer* Window::AsToplevelWindowContainer() { - return NULL; -} - -const ToplevelWindowContainer* Window::AsToplevelWindowContainer() const { - return NULL; -} - void Window::SetTransform(const ui::Transform& transform) { layer()->SetTransform(transform); } @@ -213,7 +205,7 @@ void Window::MoveChildAbove(Window* child, Window* other) { } bool Window::CanActivate() const { - return IsVisible() && delegate_ && delegate_->ShouldActivate(NULL); + return IsVisible() && (!delegate_ || delegate_->ShouldActivate(NULL)); } void Window::AddChild(Window* child) { @@ -387,14 +379,6 @@ bool Window::HasCapture() { return desktop && desktop->capture_window() == this; } -Window* Window::GetToplevelWindow() { - Window* window = this; - while (window && window->parent() && - !window->parent()->AsToplevelWindowContainer()) - window = window->parent(); - return window && window->parent() ? window : NULL; -} - void Window::SetProperty(const char* name, void* value) { void* old = GetProperty(name); if (value) diff --git a/ui/aura/window.h b/ui/aura/window.h index f66c04b..485bcb4 100644 --- a/ui/aura/window.h +++ b/ui/aura/window.h @@ -110,11 +110,6 @@ class AURA_EXPORT Window : public ui::LayerDelegate { // Returns true if this window is active. bool IsActive() const; - // RTTI to a container for top-level windows. Returns NULL if this window is - // not a top level window container. - virtual ToplevelWindowContainer* AsToplevelWindowContainer(); - virtual const ToplevelWindowContainer* AsToplevelWindowContainer() const; - virtual void SetTransform(const ui::Transform& transform); // Assigns a LayoutManager to size and place child windows. @@ -256,10 +251,6 @@ class AURA_EXPORT Window : public ui::LayerDelegate { // Returns true if this window has a mouse capture. bool HasCapture(); - // Returns the first ancestor whose parent window returns true from - // IsToplevelWindowContainer. - Window* GetToplevelWindow(); - // Sets the window property |value| for given |name|. Setting NULL or 0 // removes the property. It uses |ui::ViewProp| to store the property. // Please see the description of |prop_map_| for more details. diff --git a/ui/aura/window_unittest.cc b/ui/aura/window_unittest.cc index cd2d964c..e41a391 100644 --- a/ui/aura/window_unittest.cc +++ b/ui/aura/window_unittest.cc @@ -8,14 +8,15 @@ #include "base/compiler_specific.h" #include "base/stringprintf.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/aura/client/stacking_client.h" #include "ui/aura/desktop.h" #include "ui/aura/desktop_observer.h" #include "ui/aura/event.h" #include "ui/aura/focus_manager.h" #include "ui/aura/test/aura_test_base.h" #include "ui/aura/test/event_generator.h" +#include "ui/aura/test/test_windows.h" #include "ui/aura/test/test_window_delegate.h" -#include "ui/aura/toplevel_window_container.h" #include "ui/aura/window_delegate.h" #include "ui/aura/window_observer.h" #include "ui/base/hit_test.h" @@ -27,6 +28,8 @@ namespace aura { namespace test { +typedef AuraTestBase WindowTest; + namespace { // Used for verifying destruction methods are invoked. @@ -121,75 +124,6 @@ class CaptureWindowDelegateImpl : public TestWindowDelegate { DISALLOW_COPY_AND_ASSIGN(CaptureWindowDelegateImpl); }; -// A simple WindowDelegate implementation for these tests. It owns itself -// (deletes itself when the Window it is attached to is destroyed). -class ColorTestWindowDelegate : public TestWindowDelegate { - public: - ColorTestWindowDelegate(SkColor color) - : color_(color), - last_key_code_(ui::VKEY_UNKNOWN) { - } - virtual ~ColorTestWindowDelegate() {} - - ui::KeyboardCode last_key_code() const { return last_key_code_; } - - // Overridden from TestWindowDelegate: - virtual bool OnKeyEvent(KeyEvent* event) OVERRIDE { - last_key_code_ = event->key_code(); - return true; - } - virtual void OnWindowDestroyed() OVERRIDE { - delete this; - } - virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE { - canvas->GetSkCanvas()->drawColor(color_, SkXfermode::kSrc_Mode); - } - - private: - SkColor color_; - ui::KeyboardCode last_key_code_; - - DISALLOW_COPY_AND_ASSIGN(ColorTestWindowDelegate); -}; - -class WindowTest : public AuraTestBase { - public: - WindowTest() {} - virtual ~WindowTest() {} - - Window* CreateTestWindowWithId(int id, Window* parent) { - return CreateTestWindowWithDelegate(NULL, id, gfx::Rect(), parent); - } - - Window* CreateTestWindowWithBounds(const gfx::Rect& bounds, Window* parent) { - return CreateTestWindowWithDelegate(NULL, 0, bounds, parent); - } - - Window* CreateTestWindow(SkColor color, - int id, - const gfx::Rect& bounds, - Window* parent) { - return CreateTestWindowWithDelegate(new ColorTestWindowDelegate(color), - id, bounds, parent); - } - - Window* CreateTestWindowWithDelegate(WindowDelegate* delegate, - int id, - const gfx::Rect& bounds, - Window* parent) { - Window* window = new Window(delegate); - window->set_id(id); - window->Init(ui::Layer::LAYER_HAS_TEXTURE); - window->SetBounds(bounds); - window->Show(); - window->SetParent(parent); - return window; - } - - private: - DISALLOW_COPY_AND_ASSIGN(WindowTest); -}; - } // namespace TEST_F(WindowTest, GetChildById) { @@ -294,66 +228,6 @@ TEST_F(WindowTest, GetTopWindowContainingPoint) { EXPECT_EQ(NULL, root->GetTopWindowContainingPoint(gfx::Point(260, 260))); } -TEST_F(WindowTest, Focus) { - Desktop* desktop = Desktop::GetInstance(); - desktop->SetBounds(gfx::Rect(0, 0, 510, 510)); - - scoped_ptr<Window> w1( - CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500), NULL)); - scoped_ptr<Window> w11( - CreateTestWindow(SK_ColorGREEN, 11, gfx::Rect(5, 5, 100, 100), w1.get())); - scoped_ptr<Window> w111( - CreateTestWindow(SK_ColorCYAN, 111, gfx::Rect(5, 5, 75, 75), w11.get())); - scoped_ptr<Window> w1111( - CreateTestWindow(SK_ColorRED, 1111, gfx::Rect(5, 5, 50, 50), w111.get())); - scoped_ptr<Window> w12( - CreateTestWindow(SK_ColorMAGENTA, 12, gfx::Rect(10, 420, 25, 25), - w1.get())); - ColorTestWindowDelegate* w121delegate = - new ColorTestWindowDelegate(SK_ColorYELLOW); - scoped_ptr<Window> w121( - CreateTestWindowWithDelegate(w121delegate, 121, gfx::Rect(5, 5, 5, 5), - w12.get())); - ColorTestWindowDelegate* w122delegate = - new ColorTestWindowDelegate(SK_ColorRED); - scoped_ptr<Window> w122( - CreateTestWindowWithDelegate(w122delegate, 121, gfx::Rect(10, 5, 5, 5), - w12.get())); - scoped_ptr<Window> w13( - CreateTestWindow(SK_ColorGRAY, 13, gfx::Rect(5, 470, 50, 50), w1.get())); - - // Click on a sub-window (w121) to focus it. - gfx::Point click_point = w121->bounds().CenterPoint(); - Window::ConvertPointToWindow(w121->parent(), desktop, &click_point); - MouseEvent mouse(ui::ET_MOUSE_PRESSED, click_point, ui::EF_LEFT_BUTTON_DOWN); - desktop->DispatchMouseEvent(&mouse); - internal::FocusManager* focus_manager = w121->GetFocusManager(); - EXPECT_EQ(w121.get(), focus_manager->GetFocusedWindow()); - - // The key press should be sent to the focused sub-window. - KeyEvent keyev(ui::ET_KEY_PRESSED, ui::VKEY_E, 0); - desktop->DispatchKeyEvent(&keyev); - EXPECT_EQ(ui::VKEY_E, w121delegate->last_key_code()); - - // Touch on a sub-window (w122) to focus it. - click_point = w122->bounds().CenterPoint(); - Window::ConvertPointToWindow(w122->parent(), desktop, &click_point); - TouchEvent touchev(ui::ET_TOUCH_PRESSED, click_point, 0); - desktop->DispatchTouchEvent(&touchev); - focus_manager = w122->GetFocusManager(); - EXPECT_EQ(w122.get(), focus_manager->GetFocusedWindow()); - - // The key press should be sent to the focused sub-window. - desktop->DispatchKeyEvent(&keyev); - EXPECT_EQ(ui::VKEY_E, w122delegate->last_key_code()); - - // Removing the focused window from parent should reset the focused window. - w12->RemoveChild(w122.get()); - EXPECT_EQ(NULL, w122->GetFocusManager()); - EXPECT_EQ(NULL, w12->GetFocusManager()->GetFocusedWindow()); - EXPECT_FALSE(desktop->DispatchKeyEvent(&keyev)); -} - // Various destruction assertions. TEST_F(WindowTest, DestroyTest) { DestroyTrackingDelegateImpl parent_delegate; @@ -589,183 +463,6 @@ TEST_F(WindowTest, MouseEnterExit) { EXPECT_FALSE(d2.exited()); } -class ActivateWindowDelegate : public TestWindowDelegate { - public: - ActivateWindowDelegate() - : activate_(true), - activated_count_(0), - lost_active_count_(0), - should_activate_count_(0) { - } - - ActivateWindowDelegate(bool activate) - : activate_(activate), - activated_count_(0), - lost_active_count_(0), - should_activate_count_(0) { - } - - void set_activate(bool v) { activate_ = v; } - int activated_count() const { return activated_count_; } - int lost_active_count() const { return lost_active_count_; } - int should_activate_count() const { return should_activate_count_; } - void Clear() { - activated_count_ = lost_active_count_ = should_activate_count_ = 0; - } - - virtual bool ShouldActivate(Event* event) OVERRIDE { - should_activate_count_++; - return activate_; - } - virtual void OnActivated() OVERRIDE { - activated_count_++; - } - virtual void OnLostActive() OVERRIDE { - lost_active_count_++; - } - - private: - bool activate_; - int activated_count_; - int lost_active_count_; - int should_activate_count_; - - DISALLOW_COPY_AND_ASSIGN(ActivateWindowDelegate); -}; - -// Various assertion testing for activating windows. -TEST_F(WindowTest, ActivateOnMouse) { - Desktop* desktop = Desktop::GetInstance(); - - ActivateWindowDelegate d1; - scoped_ptr<Window> w1( - CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50), NULL)); - ActivateWindowDelegate d2; - scoped_ptr<Window> w2( - CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(70, 70, 50, 50), NULL)); - internal::FocusManager* focus_manager = w1->GetFocusManager(); - - d1.Clear(); - d2.Clear(); - - // Activate window1. - desktop->SetActiveWindow(w1.get(), NULL); - EXPECT_EQ(w1.get(), desktop->active_window()); - EXPECT_EQ(w1.get(), focus_manager->GetFocusedWindow()); - EXPECT_EQ(1, d1.activated_count()); - EXPECT_EQ(0, d1.lost_active_count()); - d1.Clear(); - - // Click on window2. - gfx::Point press_point = w2->bounds().CenterPoint(); - Window::ConvertPointToWindow(w2->parent(), desktop, &press_point); - EventGenerator generator(press_point); - generator.ClickLeftButton(); - - // Window2 should have become active. - EXPECT_EQ(w2.get(), desktop->active_window()); - EXPECT_EQ(w2.get(), focus_manager->GetFocusedWindow()); - EXPECT_EQ(0, d1.activated_count()); - EXPECT_EQ(1, d1.lost_active_count()); - EXPECT_EQ(1, d2.activated_count()); - EXPECT_EQ(0, d2.lost_active_count()); - d1.Clear(); - d2.Clear(); - - // Click back on window1, but set it up so w1 doesn't activate on click. - press_point = w1->bounds().CenterPoint(); - Window::ConvertPointToWindow(w1->parent(), desktop, &press_point); - d1.set_activate(false); - generator.ClickLeftButton(); - - // Window2 should still be active and focused. - EXPECT_EQ(w2.get(), desktop->active_window()); - EXPECT_EQ(w2.get(), focus_manager->GetFocusedWindow()); - EXPECT_EQ(0, d1.activated_count()); - EXPECT_EQ(0, d1.lost_active_count()); - EXPECT_EQ(0, d2.activated_count()); - EXPECT_EQ(0, d2.lost_active_count()); - d1.Clear(); - d2.Clear(); - - // Destroy window2, this should make window1 active. - d1.set_activate(true); - w2.reset(); - EXPECT_EQ(0, d2.activated_count()); - EXPECT_EQ(0, d2.lost_active_count()); - EXPECT_EQ(w1.get(), desktop->active_window()); - EXPECT_EQ(w1.get(), focus_manager->GetFocusedWindow()); - EXPECT_EQ(1, d1.activated_count()); - EXPECT_EQ(0, d1.lost_active_count()); -} - -// Essentially the same as ActivateOnMouse, but for touch events. -TEST_F(WindowTest, ActivateOnTouch) { - Desktop* desktop = Desktop::GetInstance(); - - ActivateWindowDelegate d1; - scoped_ptr<Window> w1( - CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50), NULL)); - ActivateWindowDelegate d2; - scoped_ptr<Window> w2( - CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(70, 70, 50, 50), NULL)); - internal::FocusManager* focus_manager = w1->GetFocusManager(); - - d1.Clear(); - d2.Clear(); - - // Activate window1. - desktop->SetActiveWindow(w1.get(), NULL); - EXPECT_EQ(w1.get(), desktop->active_window()); - EXPECT_EQ(w1.get(), focus_manager->GetFocusedWindow()); - EXPECT_EQ(1, d1.activated_count()); - EXPECT_EQ(0, d1.lost_active_count()); - d1.Clear(); - - // Touch window2. - gfx::Point press_point = w2->bounds().CenterPoint(); - Window::ConvertPointToWindow(w2->parent(), desktop, &press_point); - TouchEvent touchev1(ui::ET_TOUCH_PRESSED, press_point, 0); - desktop->DispatchTouchEvent(&touchev1); - - // Window2 should have become active. - EXPECT_EQ(w2.get(), desktop->active_window()); - EXPECT_EQ(w2.get(), focus_manager->GetFocusedWindow()); - EXPECT_EQ(0, d1.activated_count()); - EXPECT_EQ(1, d1.lost_active_count()); - EXPECT_EQ(1, d2.activated_count()); - EXPECT_EQ(0, d2.lost_active_count()); - d1.Clear(); - d2.Clear(); - - // Touch window1, but set it up so w1 doesn't activate on touch. - press_point = w1->bounds().CenterPoint(); - Window::ConvertPointToWindow(w1->parent(), desktop, &press_point); - d1.set_activate(false); - TouchEvent touchev2(ui::ET_TOUCH_PRESSED, press_point, 0); - desktop->DispatchTouchEvent(&touchev2); - - // Window2 should still be active and focused. - EXPECT_EQ(w2.get(), desktop->active_window()); - EXPECT_EQ(w2.get(), focus_manager->GetFocusedWindow()); - EXPECT_EQ(0, d1.activated_count()); - EXPECT_EQ(0, d1.lost_active_count()); - EXPECT_EQ(0, d2.activated_count()); - EXPECT_EQ(0, d2.lost_active_count()); - d1.Clear(); - d2.Clear(); - - // Destroy window2, this should make window1 active. - d1.set_activate(true); - w2.reset(); - EXPECT_EQ(0, d2.activated_count()); - EXPECT_EQ(0, d2.lost_active_count()); - EXPECT_EQ(w1.get(), desktop->active_window()); - EXPECT_EQ(w1.get(), focus_manager->GetFocusedWindow()); - EXPECT_EQ(1, d1.activated_count()); - EXPECT_EQ(0, d1.lost_active_count()); -} - namespace { class ActiveWindowDelegate : public TestWindowDelegate { @@ -1074,48 +771,6 @@ TEST_F(WindowTest, TransientChildren) { EXPECT_EQ(w1.get(), parent->children()[1]); } -class ToplevelWindowTest : public WindowTest { - public: - ToplevelWindowTest() {} - virtual ~ToplevelWindowTest() {} - - virtual void SetUp() OVERRIDE { - WindowTest::SetUp(); - toplevel_container_.Init(ui::Layer::LAYER_HAS_NO_TEXTURE); - toplevel_container_.SetParent(aura::Desktop::GetInstance()); - toplevel_container_.SetBounds( - aura::Desktop::GetInstance()->bounds()); - toplevel_container_.Show(); - } - - virtual void TearDown() OVERRIDE { - toplevel_container_.Hide(); - toplevel_container_.SetParent(NULL); - WindowTest::TearDown(); - } - - Window* CreateTestToplevelWindow( - WindowDelegate* delegate, const gfx::Rect& bounds) { - return CreateTestWindowWithDelegate( - delegate, 0 /* id */, bounds, &toplevel_container_); - } - - ToplevelWindowContainer toplevel_container_; - - private: - DISALLOW_COPY_AND_ASSIGN(ToplevelWindowTest); -}; - -TEST_F(ToplevelWindowTest, TopMostActivate) { - ActivateWindowDelegate activate; - ActivateWindowDelegate non_activate(false); - - scoped_ptr<Window> w1(CreateTestToplevelWindow(&non_activate, gfx::Rect())); - scoped_ptr<Window> w2(CreateTestToplevelWindow(&activate, gfx::Rect())); - scoped_ptr<Window> w3(CreateTestToplevelWindow(&non_activate, gfx::Rect())); - EXPECT_EQ(w2.get(), toplevel_container_.GetTopmostWindowToActivate(NULL)); -} - TEST_F(WindowTest, Property) { scoped_ptr<Window> w(CreateTestWindowWithId(0, NULL)); const char* key = "test"; diff --git a/ui/aura_shell/aura_shell.gyp b/ui/aura_shell/aura_shell.gyp index dd946b9..9a9fb01 100644 --- a/ui/aura_shell/aura_shell.gyp +++ b/ui/aura_shell/aura_shell.gyp @@ -39,6 +39,8 @@ 'default_container_layout_manager.h', 'desktop_background_view.cc', 'desktop_background_view.h', + 'desktop_event_filter.cc', + 'desktop_event_filter.h', 'desktop_layout_manager.cc', 'desktop_layout_manager.h', 'launcher/app_launcher_button.cc', @@ -68,6 +70,8 @@ 'shell_window_ids.h', 'show_state_controller.h', 'show_state_controller.cc', + 'stacking_controller.cc', + 'stacking_controller.h', 'status_area_view.cc', 'status_area_view.h', 'toplevel_frame_view.cc', @@ -112,16 +116,18 @@ ], 'sources': [ 'default_container_layout_manager_unittest.cc', + 'desktop_event_filter_unittest.cc', 'launcher/launcher_model_unittest.cc', 'launcher/view_model_unittest.cc', 'launcher/view_model_utils_unittest.cc', + 'run_all_unittests.cc', + 'stacking_controller_unittest.cc', + 'test_suite.cc', + 'test_suite.h', 'toplevel_layout_manager_unittest.cc', 'toplevel_window_event_filter_unittest.cc', 'workspace_controller_unittest.cc', 'workspace/workspace_manager_unittest.cc', - 'run_all_unittests.cc', - 'test_suite.cc', - 'test_suite.h', '<(SHARED_INTERMEDIATE_DIR)/ui/gfx/gfx_resources.rc', '<(SHARED_INTERMEDIATE_DIR)/ui/ui_resources/ui_resources.rc', diff --git a/ui/aura_shell/default_container_event_filter.cc b/ui/aura_shell/default_container_event_filter.cc index 899f46b..725beb8 100644 --- a/ui/aura_shell/default_container_event_filter.cc +++ b/ui/aura_shell/default_container_event_filter.cc @@ -7,6 +7,7 @@ #include "ui/aura/event.h" #include "ui/aura/window.h" #include "ui/aura_shell/default_container_layout_manager.h" +#include "ui/aura_shell/stacking_controller.h" #include "ui/aura_shell/window_frame.h" #include "ui/base/hit_test.h" @@ -76,7 +77,7 @@ bool DefaultContainerEventFilter::PreHandleMouseEvent(aura::Window* target, } break; case ui::ET_MOUSE_ENTERED: - UpdateHoveredWindow(target->GetToplevelWindow()); + UpdateHoveredWindow(StackingController::GetActivatableWindow(target)); break; case ui::ET_MOUSE_EXITED: UpdateHoveredWindow(NULL); diff --git a/ui/aura_shell/desktop_event_filter.cc b/ui/aura_shell/desktop_event_filter.cc new file mode 100644 index 0000000..3d17865 --- /dev/null +++ b/ui/aura_shell/desktop_event_filter.cc @@ -0,0 +1,109 @@ +// Copyright (c) 2011 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. + +#include "ui/aura_shell/desktop_event_filter.h" + +#include "ui/aura/desktop.h" +#include "ui/aura/event.h" +#include "ui/aura/focus_manager.h" +#include "ui/aura/window_delegate.h" +#include "ui/aura_shell/shell.h" +#include "ui/aura_shell/stacking_controller.h" +#include "ui/base/hit_test.h" + +namespace aura_shell { +namespace internal { + +// Returns the default cursor for a window component. +gfx::NativeCursor CursorForWindowComponent(int window_component) { + switch (window_component) { + case HTBOTTOM: + return aura::kCursorSouthResize; + case HTBOTTOMLEFT: + return aura::kCursorSouthWestResize; + case HTBOTTOMRIGHT: + return aura::kCursorSouthEastResize; + case HTLEFT: + return aura::kCursorWestResize; + case HTRIGHT: + return aura::kCursorEastResize; + case HTTOP: + return aura::kCursorNorthResize; + case HTTOPLEFT: + return aura::kCursorNorthWestResize; + case HTTOPRIGHT: + return aura::kCursorNorthEastResize; + default: + return aura::kCursorNull; + } +} + +//////////////////////////////////////////////////////////////////////////////// +// DesktopEventFilter, public: + +DesktopEventFilter::DesktopEventFilter() + : EventFilter(aura::Desktop::GetInstance()) { +} + +DesktopEventFilter::~DesktopEventFilter() { +} + +//////////////////////////////////////////////////////////////////////////////// +// DesktopEventFilter, EventFilter implementation: + +bool DesktopEventFilter::PreHandleKeyEvent(aura::Window* target, + aura::KeyEvent* event) { + return false; +} + +bool DesktopEventFilter::PreHandleMouseEvent(aura::Window* target, + aura::MouseEvent* event) { + switch (event->type()) { + case ui::ET_MOUSE_PRESSED: + ActivateIfNecessary(target, event); + break; + case ui::ET_MOUSE_MOVED: + HandleMouseMoved(target, event); + break; + default: + break; + } + return false; +} + +ui::TouchStatus DesktopEventFilter::PreHandleTouchEvent( + aura::Window* target, + aura::TouchEvent* event) { + if (event->type() == ui::ET_TOUCH_PRESSED) + ActivateIfNecessary(target, event); + return ui::TOUCH_STATUS_UNKNOWN; +} + +//////////////////////////////////////////////////////////////////////////////// +// DesktopEventFilter, private: + +void DesktopEventFilter::ActivateIfNecessary(aura::Window* window, + aura::Event* event) { + aura::Window* activatable = StackingController::GetActivatableWindow(window); + if (activatable == aura::Desktop::GetInstance()->active_window()) { + // |window| is a descendant of the active window, no need to activate. + window->GetFocusManager()->SetFocusedWindow(window); + } else { + aura::Desktop::GetInstance()->SetActiveWindow(activatable, window); + } +} + +void DesktopEventFilter::HandleMouseMoved(aura::Window* target, + aura::MouseEvent* event) { + gfx::NativeCursor cursor = target->GetCursor(event->location()); + if (event->flags() & ui::EF_IS_NON_CLIENT) { + int window_component = + target->delegate()->GetNonClientComponent(event->location()); + cursor = CursorForWindowComponent(window_component); + } + aura::Desktop::GetInstance()->SetCursor(cursor); +} + +} // namespace internal +} // namespace aura_shell diff --git a/ui/aura_shell/desktop_event_filter.h b/ui/aura_shell/desktop_event_filter.h new file mode 100644 index 0000000..1ad0438 --- /dev/null +++ b/ui/aura_shell/desktop_event_filter.h @@ -0,0 +1,43 @@ +// Copyright (c) 2011 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. + +#ifndef UI_AURA_SHELL_DESKTOP_EVENT_FILTER_H_ +#define UI_AURA_SHELL_DESKTOP_EVENT_FILTER_H_ +#pragma once + +#include "base/compiler_specific.h" +#include "ui/aura/event_filter.h" +#include "ui/aura_shell/aura_shell_export.h" + +namespace aura_shell { +namespace internal { + +class AURA_SHELL_EXPORT DesktopEventFilter : public aura::EventFilter { + public: + DesktopEventFilter(); + virtual ~DesktopEventFilter(); + + // Overridden from EventFilter: + virtual bool PreHandleKeyEvent(aura::Window* target, + aura::KeyEvent* event) OVERRIDE; + virtual bool PreHandleMouseEvent(aura::Window* target, + aura::MouseEvent* event) OVERRIDE; + virtual ui::TouchStatus PreHandleTouchEvent(aura::Window* target, + aura::TouchEvent* event) OVERRIDE; + + private: + // If necessary, activates |window| and changes focus. + void ActivateIfNecessary(aura::Window* window, aura::Event* event); + + // Updates the cursor if the target provides a custom one, and provides + // default resize cursors for window edges. + void HandleMouseMoved(aura::Window* target, aura::MouseEvent* event); + + DISALLOW_COPY_AND_ASSIGN(DesktopEventFilter); +}; + +} // namespace internal +} // namespace aura_shell + +#endif // UI_AURA_SHELL_DESKTOP_EVENT_FILTER_H_ diff --git a/ui/aura_shell/desktop_event_filter_unittest.cc b/ui/aura_shell/desktop_event_filter_unittest.cc new file mode 100644 index 0000000..05118da --- /dev/null +++ b/ui/aura_shell/desktop_event_filter_unittest.cc @@ -0,0 +1,319 @@ +// Copyright (c) 2011 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. + +#include "ui/aura_shell/desktop_event_filter.h" + +#include "ui/aura/cursor.h" +#include "ui/aura/desktop.h" +#include "ui/aura/event.h" +#include "ui/aura/test/aura_test_base.h" +#include "ui/aura/test/event_generator.h" +#include "ui/aura/test/test_windows.h" +#include "ui/aura/test/test_window_delegate.h" +#include "ui/aura/test/test_stacking_client.h" +#include "ui/aura_shell/shell_window_ids.h" +#include "ui/base/hit_test.h" + +namespace aura_shell { +namespace test { + +class DefaultEventFilterTest : public aura::test::AuraTestBase { + public: + DefaultEventFilterTest() { + aura::Desktop::GetInstance()->SetEventFilter( + new internal::DesktopEventFilter); + + aura::test::TestStackingClient* stacking_client = + static_cast<aura::test::TestStackingClient*>( + aura::Desktop::GetInstance()->stacking_client()); + stacking_client->default_container()->set_id( + internal::kShellWindowId_DefaultContainer); + } + virtual ~DefaultEventFilterTest() { + aura::Desktop::GetInstance()->SetEventFilter(NULL); + } + + private: + DISALLOW_COPY_AND_ASSIGN(DefaultEventFilterTest); +}; + +class HitTestWindowDelegate : public aura::test::TestWindowDelegate { + public: + HitTestWindowDelegate() + : hittest_code_(HTNOWHERE) { + } + virtual ~HitTestWindowDelegate() {} + void set_hittest_code(int hittest_code) { hittest_code_ = hittest_code; } + + private: + // Overridden from TestWindowDelegate: + virtual int GetNonClientComponent(const gfx::Point& point) const OVERRIDE { + return hittest_code_; + } + + int hittest_code_; + + DISALLOW_COPY_AND_ASSIGN(HitTestWindowDelegate); +}; + +TEST_F(DefaultEventFilterTest, Focus) { + aura::Desktop* desktop = aura::Desktop::GetInstance(); + desktop->SetBounds(gfx::Rect(0, 0, 510, 510)); + + // Supplied ids are negative so as not to collide with shell ids. + // TODO(beng): maybe introduce a MAKE_SHELL_ID() macro that generates a safe + // id beyond shell id max? + scoped_ptr<aura::Window> w1(aura::test::CreateTestWindow( + SK_ColorWHITE, -1, gfx::Rect(10, 10, 500, 500), NULL)); + scoped_ptr<aura::Window> w11(aura::test::CreateTestWindow( + SK_ColorGREEN, -11, gfx::Rect(5, 5, 100, 100), w1.get())); + scoped_ptr<aura::Window> w111(aura::test::CreateTestWindow( + SK_ColorCYAN, -111, gfx::Rect(5, 5, 75, 75), w11.get())); + scoped_ptr<aura::Window> w1111(aura::test::CreateTestWindow( + SK_ColorRED, -1111, gfx::Rect(5, 5, 50, 50), w111.get())); + scoped_ptr<aura::Window> w12(aura::test::CreateTestWindow( + SK_ColorMAGENTA, -12, gfx::Rect(10, 420, 25, 25), w1.get())); + aura::test::ColorTestWindowDelegate* w121delegate = + new aura::test::ColorTestWindowDelegate(SK_ColorYELLOW); + scoped_ptr<aura::Window> w121(aura::test::CreateTestWindowWithDelegate( + w121delegate, -121, gfx::Rect(5, 5, 5, 5), w12.get())); + aura::test::ColorTestWindowDelegate* w122delegate = + new aura::test::ColorTestWindowDelegate(SK_ColorRED); + scoped_ptr<aura::Window> w122(aura::test::CreateTestWindowWithDelegate( + w122delegate, -122, gfx::Rect(10, 5, 5, 5), w12.get())); + scoped_ptr<aura::Window> w13(aura::test::CreateTestWindow( + SK_ColorGRAY, -13, gfx::Rect(5, 470, 50, 50), w1.get())); + + // Click on a sub-window (w121) to focus it. + gfx::Point click_point = w121->bounds().CenterPoint(); + aura::Window::ConvertPointToWindow(w121->parent(), desktop, &click_point); + aura::MouseEvent mouse(ui::ET_MOUSE_PRESSED, click_point, + ui::EF_LEFT_BUTTON_DOWN); + desktop->DispatchMouseEvent(&mouse); + aura::internal::FocusManager* focus_manager = w121->GetFocusManager(); + EXPECT_EQ(w121.get(), focus_manager->GetFocusedWindow()); + + // The key press should be sent to the focused sub-window. + aura::KeyEvent keyev(ui::ET_KEY_PRESSED, ui::VKEY_E, 0); + desktop->DispatchKeyEvent(&keyev); + EXPECT_EQ(ui::VKEY_E, w121delegate->last_key_code()); + + // Touch on a sub-window (w122) to focus it. + click_point = w122->bounds().CenterPoint(); + aura::Window::ConvertPointToWindow(w122->parent(), desktop, &click_point); + aura::TouchEvent touchev(ui::ET_TOUCH_PRESSED, click_point, 0); + desktop->DispatchTouchEvent(&touchev); + focus_manager = w122->GetFocusManager(); + EXPECT_EQ(w122.get(), focus_manager->GetFocusedWindow()); + + // The key press should be sent to the focused sub-window. + desktop->DispatchKeyEvent(&keyev); + EXPECT_EQ(ui::VKEY_E, w122delegate->last_key_code()); + + // Removing the focused window from parent should reset the focused window. + w12->RemoveChild(w122.get()); + EXPECT_EQ(NULL, w122->GetFocusManager()); + EXPECT_EQ(NULL, w12->GetFocusManager()->GetFocusedWindow()); + EXPECT_FALSE(desktop->DispatchKeyEvent(&keyev)); +} + +// Various assertion testing for activating windows. +TEST_F(DefaultEventFilterTest, ActivateOnMouse) { + aura::Desktop* desktop = aura::Desktop::GetInstance(); + + aura::test::ActivateWindowDelegate d1; + scoped_ptr<aura::Window> w1(aura::test::CreateTestWindowWithDelegate( + &d1, 1, gfx::Rect(10, 10, 50, 50), NULL)); + aura::test::ActivateWindowDelegate d2; + scoped_ptr<aura::Window> w2(aura::test::CreateTestWindowWithDelegate( + &d2, 2, gfx::Rect(70, 70, 50, 50), NULL)); + aura::internal::FocusManager* focus_manager = w1->GetFocusManager(); + + d1.Clear(); + d2.Clear(); + + // Activate window1. + desktop->SetActiveWindow(w1.get(), NULL); + EXPECT_EQ(w1.get(), desktop->active_window()); + EXPECT_EQ(w1.get(), focus_manager->GetFocusedWindow()); + EXPECT_EQ(1, d1.activated_count()); + EXPECT_EQ(0, d1.lost_active_count()); + d1.Clear(); + + // Click on window2. + gfx::Point press_point = w2->bounds().CenterPoint(); + aura::Window::ConvertPointToWindow(w2->parent(), desktop, &press_point); + aura::test::EventGenerator generator(press_point); + generator.ClickLeftButton(); + + // Window2 should have become active. + EXPECT_EQ(w2.get(), desktop->active_window()); + EXPECT_EQ(w2.get(), focus_manager->GetFocusedWindow()); + EXPECT_EQ(0, d1.activated_count()); + EXPECT_EQ(1, d1.lost_active_count()); + EXPECT_EQ(1, d2.activated_count()); + EXPECT_EQ(0, d2.lost_active_count()); + d1.Clear(); + d2.Clear(); + + // Click back on window1, but set it up so w1 doesn't activate on click. + press_point = w1->bounds().CenterPoint(); + aura::Window::ConvertPointToWindow(w1->parent(), desktop, &press_point); + d1.set_activate(false); + generator.ClickLeftButton(); + + // Window2 should still be active and focused. + EXPECT_EQ(w2.get(), desktop->active_window()); + EXPECT_EQ(w2.get(), focus_manager->GetFocusedWindow()); + EXPECT_EQ(0, d1.activated_count()); + EXPECT_EQ(0, d1.lost_active_count()); + EXPECT_EQ(0, d2.activated_count()); + EXPECT_EQ(0, d2.lost_active_count()); + d1.Clear(); + d2.Clear(); + + // Destroy window2, this should make window1 active. + d1.set_activate(true); + w2.reset(); + EXPECT_EQ(0, d2.activated_count()); + EXPECT_EQ(0, d2.lost_active_count()); + EXPECT_EQ(w1.get(), desktop->active_window()); + EXPECT_EQ(w1.get(), focus_manager->GetFocusedWindow()); + EXPECT_EQ(1, d1.activated_count()); + EXPECT_EQ(0, d1.lost_active_count()); +} + +// Essentially the same as ActivateOnMouse, but for touch events. +TEST_F(DefaultEventFilterTest, ActivateOnTouch) { + aura::Desktop* desktop = aura::Desktop::GetInstance(); + + aura::test::ActivateWindowDelegate d1; + scoped_ptr<aura::Window> w1(aura::test::CreateTestWindowWithDelegate( + &d1, -1, gfx::Rect(10, 10, 50, 50), NULL)); + aura::test::ActivateWindowDelegate d2; + scoped_ptr<aura::Window> w2(aura::test::CreateTestWindowWithDelegate( + &d2, -2, gfx::Rect(70, 70, 50, 50), NULL)); + aura::internal::FocusManager* focus_manager = w1->GetFocusManager(); + + d1.Clear(); + d2.Clear(); + + // Activate window1. + desktop->SetActiveWindow(w1.get(), NULL); + EXPECT_EQ(w1.get(), desktop->active_window()); + EXPECT_EQ(w1.get(), focus_manager->GetFocusedWindow()); + EXPECT_EQ(1, d1.activated_count()); + EXPECT_EQ(0, d1.lost_active_count()); + d1.Clear(); + + // Touch window2. + gfx::Point press_point = w2->bounds().CenterPoint(); + aura::Window::ConvertPointToWindow(w2->parent(), desktop, &press_point); + aura::TouchEvent touchev1(ui::ET_TOUCH_PRESSED, press_point, 0); + desktop->DispatchTouchEvent(&touchev1); + + // Window2 should have become active. + EXPECT_EQ(w2.get(), desktop->active_window()); + EXPECT_EQ(w2.get(), focus_manager->GetFocusedWindow()); + EXPECT_EQ(0, d1.activated_count()); + EXPECT_EQ(1, d1.lost_active_count()); + EXPECT_EQ(1, d2.activated_count()); + EXPECT_EQ(0, d2.lost_active_count()); + d1.Clear(); + d2.Clear(); + + // Touch window1, but set it up so w1 doesn't activate on touch. + press_point = w1->bounds().CenterPoint(); + aura::Window::ConvertPointToWindow(w1->parent(), desktop, &press_point); + d1.set_activate(false); + aura::TouchEvent touchev2(ui::ET_TOUCH_PRESSED, press_point, 0); + desktop->DispatchTouchEvent(&touchev2); + + // Window2 should still be active and focused. + EXPECT_EQ(w2.get(), desktop->active_window()); + EXPECT_EQ(w2.get(), focus_manager->GetFocusedWindow()); + EXPECT_EQ(0, d1.activated_count()); + EXPECT_EQ(0, d1.lost_active_count()); + EXPECT_EQ(0, d2.activated_count()); + EXPECT_EQ(0, d2.lost_active_count()); + d1.Clear(); + d2.Clear(); + + // Destroy window2, this should make window1 active. + d1.set_activate(true); + w2.reset(); + EXPECT_EQ(0, d2.activated_count()); + EXPECT_EQ(0, d2.lost_active_count()); + EXPECT_EQ(w1.get(), desktop->active_window()); + EXPECT_EQ(w1.get(), focus_manager->GetFocusedWindow()); + EXPECT_EQ(1, d1.activated_count()); + EXPECT_EQ(0, d1.lost_active_count()); +} + +TEST_F(DefaultEventFilterTest, MouseEventCursors) { + aura::Desktop* desktop = aura::Desktop::GetInstance(); + + // Create a window. + const int kWindowLeft = 123; + const int kWindowTop = 45; + HitTestWindowDelegate window_delegate; + scoped_ptr<aura::Window> window(aura::test::CreateTestWindowWithDelegate( + &window_delegate, + -1, + gfx::Rect(kWindowLeft, kWindowTop, 640, 480), + NULL)); + + // Create two mouse movement events we can switch between. + gfx::Point point1(kWindowLeft, kWindowTop); + aura::Window::ConvertPointToWindow(window->parent(), desktop, &point1); + aura::MouseEvent move1(ui::ET_MOUSE_MOVED, point1, 0x0); + + gfx::Point point2(kWindowLeft + 1, kWindowTop + 1); + aura::Window::ConvertPointToWindow(window->parent(), desktop, &point2); + aura::MouseEvent move2(ui::ET_MOUSE_MOVED, point2, 0x0); + + // Cursor starts as null. + EXPECT_EQ(aura::kCursorNull, desktop->last_cursor()); + + // Resize edges and corners show proper cursors. + window_delegate.set_hittest_code(HTBOTTOM); + desktop->DispatchMouseEvent(&move1); + EXPECT_EQ(aura::kCursorSouthResize, desktop->last_cursor()); + + window_delegate.set_hittest_code(HTBOTTOMLEFT); + desktop->DispatchMouseEvent(&move2); + EXPECT_EQ(aura::kCursorSouthWestResize, desktop->last_cursor()); + + window_delegate.set_hittest_code(HTBOTTOMRIGHT); + desktop->DispatchMouseEvent(&move1); + EXPECT_EQ(aura::kCursorSouthEastResize, desktop->last_cursor()); + + window_delegate.set_hittest_code(HTLEFT); + desktop->DispatchMouseEvent(&move2); + EXPECT_EQ(aura::kCursorWestResize, desktop->last_cursor()); + + window_delegate.set_hittest_code(HTRIGHT); + desktop->DispatchMouseEvent(&move1); + EXPECT_EQ(aura::kCursorEastResize, desktop->last_cursor()); + + window_delegate.set_hittest_code(HTTOP); + desktop->DispatchMouseEvent(&move2); + EXPECT_EQ(aura::kCursorNorthResize, desktop->last_cursor()); + + window_delegate.set_hittest_code(HTTOPLEFT); + desktop->DispatchMouseEvent(&move1); + EXPECT_EQ(aura::kCursorNorthWestResize, desktop->last_cursor()); + + window_delegate.set_hittest_code(HTTOPRIGHT); + desktop->DispatchMouseEvent(&move2); + EXPECT_EQ(aura::kCursorNorthEastResize, desktop->last_cursor()); + + // Client area uses null cursor. + window_delegate.set_hittest_code(HTCLIENT); + desktop->DispatchMouseEvent(&move1); + EXPECT_EQ(aura::kCursorNull, desktop->last_cursor()); +} + +} // namespace test +} // namespace aura_shell diff --git a/ui/aura_shell/launcher/launcher.cc b/ui/aura_shell/launcher/launcher.cc index 8459656..a10e485 100644 --- a/ui/aura_shell/launcher/launcher.cc +++ b/ui/aura_shell/launcher/launcher.cc @@ -4,7 +4,7 @@ #include "ui/aura_shell/launcher/launcher.h" -#include "ui/aura/toplevel_window_container.h" +#include "ui/aura/window.h" #include "ui/aura_shell/launcher/launcher_model.h" #include "ui/aura_shell/launcher/launcher_view.h" #include "ui/aura_shell/shell.h" @@ -15,7 +15,7 @@ namespace aura_shell { -Launcher::Launcher(aura::ToplevelWindowContainer* window_container) +Launcher::Launcher(aura::Window* window_container) : widget_(NULL), window_container_(window_container) { window_container->AddObserver(this); diff --git a/ui/aura_shell/launcher/launcher.h b/ui/aura_shell/launcher/launcher.h index a1c97de..ef1a2ac 100644 --- a/ui/aura_shell/launcher/launcher.h +++ b/ui/aura_shell/launcher/launcher.h @@ -14,7 +14,7 @@ #include "ui/aura_shell/aura_shell_export.h" namespace aura { -class ToplevelWindowContainer; +class Window; } namespace views { @@ -27,7 +27,7 @@ class LauncherModel; class AURA_SHELL_EXPORT Launcher : public aura::WindowObserver { public: - explicit Launcher(aura::ToplevelWindowContainer* window_container); + explicit Launcher(aura::Window* window_container); ~Launcher(); LauncherModel* model() { return model_.get(); } @@ -51,7 +51,7 @@ class AURA_SHELL_EXPORT Launcher : public aura::WindowObserver { // Widget hosting the view. views::Widget* widget_; - aura::ToplevelWindowContainer* window_container_; + aura::Window* window_container_; // The set of windows we know about. The boolean indicates whether we've asked // the delegate if the window should added to the launcher. diff --git a/ui/aura_shell/run_all_unittests.cc b/ui/aura_shell/run_all_unittests.cc index 950d43b..9fa9c8a 100644 --- a/ui/aura_shell/run_all_unittests.cc +++ b/ui/aura_shell/run_all_unittests.cc @@ -5,5 +5,5 @@ #include "ui/aura_shell/test_suite.h" int main(int argc, char** argv) { - return AuraShellTestSuite(argc, argv).Run(); + return aura_shell::test::AuraShellTestSuite(argc, argv).Run(); } diff --git a/ui/aura_shell/shell.cc b/ui/aura_shell/shell.cc index 58d3d78f..a9d9c81 100644 --- a/ui/aura_shell/shell.cc +++ b/ui/aura_shell/shell.cc @@ -8,17 +8,18 @@ #include "base/command_line.h" #include "ui/aura/aura_switches.h" #include "ui/aura/desktop.h" -#include "ui/aura/toplevel_window_container.h" #include "ui/aura/window.h" #include "ui/aura/window_types.h" #include "ui/aura_shell/default_container_event_filter.h" #include "ui/aura_shell/default_container_layout_manager.h" +#include "ui/aura_shell/desktop_event_filter.h" #include "ui/aura_shell/desktop_layout_manager.h" #include "ui/aura_shell/launcher/launcher.h" #include "ui/aura_shell/shelf_layout_controller.h" #include "ui/aura_shell/shell_delegate.h" #include "ui/aura_shell/shell_factory.h" #include "ui/aura_shell/shell_window_ids.h" +#include "ui/aura_shell/stacking_controller.h" #include "ui/aura_shell/toplevel_layout_manager.h" #include "ui/aura_shell/toplevel_window_event_filter.h" #include "ui/aura_shell/workspace_controller.h" @@ -42,13 +43,13 @@ void CreateSpecialContainers(aura::Window::Windows* containers) { internal::kShellWindowId_DesktopBackgroundContainer); containers->push_back(background_container); - aura::Window* default_container = new aura::ToplevelWindowContainer; + aura::Window* default_container = new aura::Window(NULL); default_container->SetEventFilter( new ToplevelWindowEventFilter(default_container)); default_container->set_id(internal::kShellWindowId_DefaultContainer); containers->push_back(default_container); - aura::Window* always_on_top_container = new aura::ToplevelWindowContainer; + aura::Window* always_on_top_container = new aura::Window(NULL); always_on_top_container->SetEventFilter( new ToplevelWindowEventFilter(always_on_top_container)); always_on_top_container->set_id( @@ -83,7 +84,10 @@ Shell* Shell::instance_ = NULL; Shell::Shell() : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { - aura::Desktop::GetInstance()->SetStackingClient(this); + aura::Desktop::GetInstance()->SetEventFilter( + new internal::DesktopEventFilter); + aura::Desktop::GetInstance()->SetStackingClient( + new internal::StackingController); } Shell::~Shell() { @@ -101,6 +105,12 @@ Shell* Shell::GetInstance() { return instance_; } +// static +void Shell::DeleteInstanceForTesting() { + delete instance_; + instance_ = NULL; +} + void Shell::Init() { aura::Desktop* desktop_window = aura::Desktop::GetInstance(); desktop_window->SetCursor(aura::kCursorPointer); @@ -119,10 +129,9 @@ void Shell::Init() { desktop_window->SetLayoutManager(desktop_layout); desktop_layout->set_background_widget(internal::CreateDesktopBackground()); - aura::ToplevelWindowContainer* toplevel_container = - GetContainer(internal::kShellWindowId_DefaultContainer)-> - AsToplevelWindowContainer(); - launcher_.reset(new Launcher(toplevel_container)); + aura::Window* default_container = + GetContainer(internal::kShellWindowId_DefaultContainer); + launcher_.reset(new Launcher(default_container)); shelf_layout_controller_.reset(new internal::ShelfLayoutController( launcher_->widget(), internal::CreateStatusArea())); @@ -133,7 +142,7 @@ void Shell::Init() { } else { internal::ToplevelLayoutManager* toplevel_layout_manager = new internal::ToplevelLayoutManager(); - toplevel_container->SetLayoutManager(toplevel_layout_manager); + default_container->SetLayoutManager(toplevel_layout_manager); toplevel_layout_manager->set_shelf(shelf_layout_controller_.get()); } @@ -176,33 +185,4 @@ void Shell::EnableWorkspaceManager() { workspace_controller_->workspace_manager())); } -//////////////////////////////////////////////////////////////////////////////// -// Shell, aura::StackingClient implementation: - -void Shell::AddChildToDefaultParent(aura::Window* window) { - aura::Window* parent = NULL; - switch (window->type()) { - case aura::WINDOW_TYPE_NORMAL: - case aura::WINDOW_TYPE_POPUP: - parent = GetContainer(internal::kShellWindowId_DefaultContainer); - break; - case aura::WINDOW_TYPE_MENU: - case aura::WINDOW_TYPE_TOOLTIP: - parent = GetContainer(internal::kShellWindowId_MenusAndTooltipsContainer); - break; - default: - NOTREACHED() << "Window " << window->id() - << " has unhandled type " << window->type(); - break; - } - parent->AddChild(window); -} - -aura::Window* Shell::GetTopmostWindowToActivate(aura::Window* ignore) const { - const aura::ToplevelWindowContainer* container = - GetContainer(internal::kShellWindowId_DefaultContainer)-> - AsToplevelWindowContainer(); - return container->GetTopmostWindowToActivate(ignore); -} - } // namespace aura_shell diff --git a/ui/aura_shell/shell.h b/ui/aura_shell/shell.h index 7021425..5abe2b0 100644 --- a/ui/aura_shell/shell.h +++ b/ui/aura_shell/shell.h @@ -14,7 +14,6 @@ #include "base/task.h" #include "base/compiler_specific.h" #include "base/memory/weak_ptr.h" -#include "ui/aura/client/stacking_client.h" #include "ui/aura_shell/aura_shell_export.h" namespace aura { @@ -36,7 +35,7 @@ class WorkspaceController; // Shell is a singleton object that presents the Shell API and implements the // Desktop's delegate interface. -class AURA_SHELL_EXPORT Shell : public aura::StackingClient { +class AURA_SHELL_EXPORT Shell { public: // Upon creation, the Shell sets itself as the Desktop's delegate, which takes // ownership of the Shell. @@ -44,6 +43,7 @@ class AURA_SHELL_EXPORT Shell : public aura::StackingClient { virtual ~Shell(); static Shell* GetInstance(); + static void DeleteInstanceForTesting(); void Init(); @@ -65,11 +65,6 @@ class AURA_SHELL_EXPORT Shell : public aura::StackingClient { // Enables WorkspaceManager. void EnableWorkspaceManager(); - // Overridden from aura::StackingClient: - virtual void AddChildToDefaultParent(aura::Window* window) OVERRIDE; - virtual aura::Window* GetTopmostWindowToActivate( - aura::Window* ignore) const OVERRIDE; - static Shell* instance_; std::vector<WindowAndBoundsPair> to_restore_; @@ -81,7 +76,6 @@ class AURA_SHELL_EXPORT Shell : public aura::StackingClient { scoped_ptr<Launcher> launcher_; scoped_ptr<internal::WorkspaceController> workspace_controller_; - scoped_ptr<internal::ShelfLayoutController> shelf_layout_controller_; DISALLOW_COPY_AND_ASSIGN(Shell); diff --git a/ui/aura_shell/stacking_controller.cc b/ui/aura_shell/stacking_controller.cc new file mode 100644 index 0000000..1371c20 --- /dev/null +++ b/ui/aura_shell/stacking_controller.cc @@ -0,0 +1,95 @@ +// Copyright (c) 2011 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. + +#include "ui/aura_shell/stacking_controller.h" + +#include "ui/aura/desktop.h" +#include "ui/aura/window.h" +#include "ui/aura_shell/shell.h" +#include "ui/aura_shell/shell_window_ids.h" + +namespace aura_shell { +namespace internal { +namespace { + +aura::Window* GetContainer(int id) { + return Shell::GetInstance()->GetContainer(id); +} + +// Returns true if children of |window| can be activated. +bool SupportsChildActivation(aura::Window* window) { + return window->id() == kShellWindowId_DefaultContainer || + window->id() == kShellWindowId_AlwaysOnTopContainer; +} + +} // namespace + +//////////////////////////////////////////////////////////////////////////////// +// StackingController, public: + +StackingController::StackingController() { + aura::Desktop::GetInstance()->SetStackingClient(this); +} + +StackingController::~StackingController() { +} + +// static +aura::Window* StackingController::GetActivatableWindow(aura::Window* window) { + aura::Window* parent = window->parent(); + aura::Window* child = window; + while (parent) { + if (SupportsChildActivation(parent)) + return child; + parent = parent->parent(); + child = child->parent(); + } + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +// StackingController, aura::StackingClient implementation: + +void StackingController::AddChildToDefaultParent(aura::Window* window) { + aura::Window* parent = NULL; + switch (window->type()) { + case aura::WINDOW_TYPE_NORMAL: + case aura::WINDOW_TYPE_POPUP: + parent = GetContainer(internal::kShellWindowId_DefaultContainer); + break; + case aura::WINDOW_TYPE_MENU: + case aura::WINDOW_TYPE_TOOLTIP: + parent = GetContainer(internal::kShellWindowId_MenusAndTooltipsContainer); + break; + default: + NOTREACHED() << "Window " << window->id() + << " has unhandled type " << window->type(); + break; + } + parent->AddChild(window); +} + +bool StackingController::CanActivateWindow(aura::Window* window) const { + return window && SupportsChildActivation(window->parent()); +} + +aura::Window* StackingController::GetTopmostWindowToActivate( + aura::Window* ignore) const { + const aura::Window* container = GetContainer(kShellWindowId_DefaultContainer); + for (aura::Window::Windows::const_reverse_iterator i = + container->children().rbegin(); + i != container->children().rend(); + ++i) { + if (*i != ignore && (*i)->CanActivate()) + return *i; + } + return NULL; +} + + +//////////////////////////////////////////////////////////////////////////////// +// StackingController, private: + +} // namespace internal +} // namespace aura_shell diff --git a/ui/aura_shell/stacking_controller.h b/ui/aura_shell/stacking_controller.h new file mode 100644 index 0000000..2091f1f --- /dev/null +++ b/ui/aura_shell/stacking_controller.h @@ -0,0 +1,38 @@ +// Copyright (c) 2011 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. + +#ifndef UI_AURA_SHELL_STACKING_CONTROLLER_H_ +#define UI_AURA_SHELL_STACKING_CONTROLLER_H_ +#pragma once + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "ui/aura/client/stacking_client.h" + +namespace aura_shell { +namespace internal { + +class StackingController : public aura::StackingClient { + public: + StackingController(); + virtual ~StackingController(); + + // Returns true if |window| exists within a container that supports + // activation. + static aura::Window* GetActivatableWindow(aura::Window* window); + + // Overridden from aura::StackingClient: + virtual void AddChildToDefaultParent(aura::Window* window) OVERRIDE; + virtual bool CanActivateWindow(aura::Window* window) const OVERRIDE; + virtual aura::Window* GetTopmostWindowToActivate( + aura::Window* ignore) const OVERRIDE; + + private: + DISALLOW_COPY_AND_ASSIGN(StackingController); +}; + +} // namespace internal +} // namespace aura_shell + +#endif // UI_AURA_SHELL_STACKING_CONTROLLER_H_ diff --git a/ui/aura_shell/stacking_controller_unittest.cc b/ui/aura_shell/stacking_controller_unittest.cc new file mode 100644 index 0000000..a7cd2c9 --- /dev/null +++ b/ui/aura_shell/stacking_controller_unittest.cc @@ -0,0 +1,34 @@ +// Copyright (c) 2011 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. + +#include "ui/aura_shell/stacking_controller.h" + +#include "ui/aura/desktop.h" +#include "ui/aura/test/aura_test_base.h" +#include "ui/aura/test/test_windows.h" +#include "ui/aura/test/test_window_delegate.h" +#include "ui/aura_shell/shell.h" + +namespace aura_shell { +namespace test { + +typedef aura::test::AuraTestBase StackingControllerTest; + +TEST_F(StackingControllerTest, GetTopmostWindowToActivate) { + Shell::GetInstance(); + aura::test::ActivateWindowDelegate activate; + aura::test::ActivateWindowDelegate non_activate(false); + + scoped_ptr<aura::Window> w1(aura::test::CreateTestWindowWithDelegate( + &non_activate, 1, gfx::Rect(), NULL)); + scoped_ptr<aura::Window> w2(aura::test::CreateTestWindowWithDelegate( + &activate, 2, gfx::Rect(), NULL)); + scoped_ptr<aura::Window> w3(aura::test::CreateTestWindowWithDelegate( + &non_activate, 3, gfx::Rect(), NULL)); + EXPECT_EQ(w2.get(), aura::Desktop::GetInstance()->stacking_client()-> + GetTopmostWindowToActivate(NULL)); +} + +} // namespace test +} // namespace aura_shell diff --git a/ui/aura_shell/test_suite.cc b/ui/aura_shell/test_suite.cc index 557bd95..fcd3a8f 100644 --- a/ui/aura_shell/test_suite.cc +++ b/ui/aura_shell/test_suite.cc @@ -13,6 +13,9 @@ #include "ui/gfx/gfx_paths.h" #include "ui/gfx/test/gfx_test_utils.h" +namespace aura_shell { +namespace test { + AuraShellTestSuite::AuraShellTestSuite(int argc, char** argv) : TestSuite(argc, argv) {} @@ -35,3 +38,6 @@ void AuraShellTestSuite::Shutdown() { base::TestSuite::Shutdown(); } + +} // namespace test +} // namespace aura_shell diff --git a/ui/aura_shell/test_suite.h b/ui/aura_shell/test_suite.h index 72e946c..fac7daf 100644 --- a/ui/aura_shell/test_suite.h +++ b/ui/aura_shell/test_suite.h @@ -9,6 +9,9 @@ #include "base/compiler_specific.h" #include "base/test/test_suite.h" +namespace aura_shell { +namespace test { + class AuraShellTestSuite : public base::TestSuite { public: AuraShellTestSuite(int argc, char** argv); @@ -19,4 +22,7 @@ class AuraShellTestSuite : public base::TestSuite { virtual void Shutdown() OVERRIDE; }; +} // namespace test +} // namespace aura_shell + #endif // UI_AURA_SHELL_TEST_SUITE_H_ diff --git a/ui/aura_shell/toplevel_layout_manager.h b/ui/aura_shell/toplevel_layout_manager.h index 0593e8d..d8774fe 100644 --- a/ui/aura_shell/toplevel_layout_manager.h +++ b/ui/aura_shell/toplevel_layout_manager.h @@ -19,10 +19,10 @@ namespace internal { class ShelfLayoutController; -// ToplevelLayoutManager is the LayoutManager installed on the -// ToplevelWindowContainer. It is used if the WorkspaceManager is not -// enabled. ToplevelLayoutManager listens for changes to kShowStateKey and -// resizes the window appropriately. +// ToplevelLayoutManager is the LayoutManager installed on a container that +// hosts what the shell considers to be top-level windows. It is used if the +// WorkspaceManager is not enabled. ToplevelLayoutManager listens for changes to +// kShowStateKey and resizes the window appropriately. class AURA_SHELL_EXPORT ToplevelLayoutManager : public aura::LayoutManager, public aura::WindowObserver { public: diff --git a/ui/aura_shell/workspace_controller_unittest.cc b/ui/aura_shell/workspace_controller_unittest.cc index 6f3241b..7128a40 100644 --- a/ui/aura_shell/workspace_controller_unittest.cc +++ b/ui/aura_shell/workspace_controller_unittest.cc @@ -35,6 +35,7 @@ class WorkspaceControllerTest : public aura::test::AuraTestBase { aura::Window* window = new aura::Window(NULL); window->Init(ui::Layer::LAYER_HAS_NO_TEXTURE); contents_view()->AddChild(window); + window->Show(); return window; } @@ -61,7 +62,6 @@ TEST_F(WorkspaceControllerTest, Overview) { // and ws2 which contains window w2. Workspace* ws1 = workspace_manager()->CreateWorkspace(); scoped_ptr<Window> w1(CreateTestWindow()); - EXPECT_TRUE(ws1->AddWindowAfter(w1.get(), NULL)); Workspace* ws2 = workspace_manager()->CreateWorkspace(); @@ -81,7 +81,7 @@ TEST_F(WorkspaceControllerTest, Overview) { // Switching overview mode doesn't change the active workspace. EXPECT_EQ(ws2, workspace_manager()->GetActiveWorkspace()); - // Activaing window w1 switches the active window and + // Activating window w1 switches the active window and // the mode back to normal mode. w1->Activate(); EXPECT_EQ(ws1, workspace_manager()->GetActiveWorkspace()); @@ -91,7 +91,7 @@ TEST_F(WorkspaceControllerTest, Overview) { ws1->RemoveWindow(w1.get()); delete ws1; w1.reset(); - EXPECT_EQ(NULL, workspace_manager()->GetActiveWorkspace()); + EXPECT_EQ(ws2, workspace_manager()->GetActiveWorkspace()); EXPECT_EQ("0,0 500x300", contents_view()->bounds().ToString()); ws2->RemoveWindow(w2.get()); delete ws2; diff --git a/views/widget/native_widget_aura.cc b/views/widget/native_widget_aura.cc index 7326fe4..8da5452 100644 --- a/views/widget/native_widget_aura.cc +++ b/views/widget/native_widget_aura.cc @@ -680,9 +680,6 @@ NativeWidgetPrivate* NativeWidgetPrivate::GetNativeWidgetForNativeWindow( // static NativeWidgetPrivate* NativeWidgetPrivate::GetTopLevelNativeWidget( gfx::NativeView native_view) { - if (!native_view) - return NULL; - aura::Window* window = native_view; NativeWidgetPrivate* top_level_native_widget = NULL; while (window) { |