diff options
author | Jocelyn Turcotte <jocelyn.turcotte@digia.com> | 2014-08-08 14:30:41 +0200 |
---|---|---|
committer | Jocelyn Turcotte <jocelyn.turcotte@digia.com> | 2014-08-12 13:49:54 +0200 |
commit | ab0a50979b9eb4dfa3320eff7e187e41efedf7a9 (patch) | |
tree | 498dfb8a97ff3361a9f7486863a52bb4e26bb898 /chromium/ui/views/corewm | |
parent | 4ce69f7403811819800e7c5ae1318b2647e778d1 (diff) |
Update Chromium to beta version 37.0.2062.68
Change-Id: I188e3b5aff1bec75566014291b654eb19f5bc8ca
Reviewed-by: Andras Becsi <andras.becsi@digia.com>
Diffstat (limited to 'chromium/ui/views/corewm')
61 files changed, 826 insertions, 7821 deletions
diff --git a/chromium/ui/views/corewm/DEPS b/chromium/ui/views/corewm/DEPS index 06abf634093..a2d52d61d09 100644 --- a/chromium/ui/views/corewm/DEPS +++ b/chromium/ui/views/corewm/DEPS @@ -1,4 +1,57 @@ -# This code should not depend on Views.
-
-"-ui/views",
-"+ui/views/views_export.h"
+# This code should not depend on Views. + +include_rules = [ + "-ui/views", + "+ui/views/corewm", + "+ui/views/views_export.h", +] + +# TODO: temporary, don't add more. +specific_include_rules = { + "tooltip_controller.cc": [ + "+ui/views/widget/tooltip_manager.h", + ], + + "tooltip_aura.cc": [ + "+ui/views/background.h", + "+ui/views/border.h", + "+ui/views/widget/widget.h", + ], + + "desktop_capture_controller_unittest.cc": [ + "+ui/views/test/views_test_base.h", + "+ui/views/view.h", + "+ui/views/widget/desktop_aura/desktop_native_widget_aura.h", + "+ui/views/widget/desktop_aura/desktop_screen_position_client.h", + "+ui/views/widget/root_view.h", + "+ui/views/widget/widget.h", + ], + + "tooltip_controller_unittest.cc": [ + "+ui/views/test/desktop_test_views_delegate.h", + "+ui/views/test/test_views_delegate.h", + "+ui/views/view.h", + "+ui/views/widget/desktop_aura/desktop_native_widget_aura.h", + "+ui/views/widget/desktop_aura/desktop_screen.h", + "+ui/views/widget/tooltip_manager.h", + "+ui/views/widget/widget.h", + ], + + "tooltip_aura.h": [ + "+ui/views/controls/label.h", + "+ui/views/widget/widget_observer.h", + ], + + "tooltip_controller_test_helper.h": [ + "+ui/views/view.h", + ], + + "capture_controller_unittest.cc": [ + "+ui/views/test/views_test_base.h", + "+ui/views/view.h", + "+ui/views/widget/desktop_aura/desktop_native_widget_aura.h", + "+ui/views/widget/desktop_aura/desktop_screen_position_client.h", + "+ui/views/widget/root_view.h", + "+ui/views/widget/widget.h", + ], +} diff --git a/chromium/ui/views/corewm/base_focus_rules.cc b/chromium/ui/views/corewm/base_focus_rules.cc deleted file mode 100644 index 9520c749cd0..00000000000 --- a/chromium/ui/views/corewm/base_focus_rules.cc +++ /dev/null @@ -1,196 +0,0 @@ -// 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. - -#include "ui/views/corewm/base_focus_rules.h" - -#include "ui/aura/client/activation_delegate.h" -#include "ui/aura/client/focus_client.h" -#include "ui/aura/root_window.h" -#include "ui/aura/window.h" -#include "ui/views/corewm/window_modality_controller.h" - -namespace views { -namespace corewm { -namespace { - -aura::Window* GetFocusedWindow(aura::Window* context) { - aura::client::FocusClient* focus_client = - aura::client::GetFocusClient(context); - return focus_client ? focus_client->GetFocusedWindow() : NULL; -} - -} // namespace - -//////////////////////////////////////////////////////////////////////////////// -// BaseFocusRules, protected: - -BaseFocusRules::BaseFocusRules() { -} - -BaseFocusRules::~BaseFocusRules() { -} - -bool BaseFocusRules::IsWindowConsideredVisibleForActivation( - aura::Window* window) const { - return window->IsVisible(); -} - -//////////////////////////////////////////////////////////////////////////////// -// BaseFocusRules, FocusRules implementation: - -bool BaseFocusRules::IsToplevelWindow(aura::Window* window) const { - // The window must in a valid hierarchy. - if (!window->GetRootWindow()) - return false; - - // The window must exist within a container that supports activation. - // The window cannot be blocked by a modal transient. - return SupportsChildActivation(window->parent()); -} - -bool BaseFocusRules::CanActivateWindow(aura::Window* window) const { - // It is possible to activate a NULL window, it is equivalent to clearing - // activation. - if (!window) - return true; - - // Only toplevel windows can be activated. - if (!IsToplevelWindow(window)) - return false; - - // The window must be visible. - if (!IsWindowConsideredVisibleForActivation(window)) - return false; - - // The window's activation delegate must allow this window to be activated. - if (aura::client::GetActivationDelegate(window) && - !aura::client::GetActivationDelegate(window)->ShouldActivate()) { - return false; - } - - // A window must be focusable to be activatable. We don't call - // CanFocusWindow() from here because it will call back to us via - // GetActivatableWindow(). - if (!window->CanFocus()) - return false; - - // The window cannot be blocked by a modal transient. - return !GetModalTransient(window); -} - -bool BaseFocusRules::CanFocusWindow(aura::Window* window) const { - // It is possible to focus a NULL window, it is equivalent to clearing focus. - if (!window) - return true; - - // The focused window is always inside the active window, so windows that - // aren't activatable can't contain the focused window. - aura::Window* activatable = GetActivatableWindow(window); - if (!activatable || !activatable->Contains(window)) - return false; - return window->CanFocus(); -} - -aura::Window* BaseFocusRules::GetToplevelWindow(aura::Window* window) const { - aura::Window* parent = window->parent(); - aura::Window* child = window; - while (parent) { - if (IsToplevelWindow(child)) - return child; - - parent = parent->parent(); - child = child->parent(); - } - return NULL; -} - -aura::Window* BaseFocusRules::GetActivatableWindow(aura::Window* window) const { - aura::Window* parent = window->parent(); - aura::Window* child = window; - while (parent) { - if (CanActivateWindow(child)) - return child; - - // CanActivateWindow() above will return false if |child| is blocked by a - // modal transient. In this case the modal is or contains the activatable - // window. We recurse because the modal may itself be blocked by a modal - // transient. - aura::Window* modal_transient = GetModalTransient(child); - if (modal_transient) - return GetActivatableWindow(modal_transient); - - if (child->transient_parent()) { - // To avoid infinite recursion, if |child| has a transient parent - // whose own modal transient is |child| itself, just return |child|. - aura::Window* parent_modal_transient = - GetModalTransient(child->transient_parent()); - if (parent_modal_transient == child) - return child; - - return GetActivatableWindow(child->transient_parent()); - } - - parent = parent->parent(); - child = child->parent(); - } - return NULL; -} - -aura::Window* BaseFocusRules::GetFocusableWindow(aura::Window* window) const { - if (CanFocusWindow(window)) - return window; - - // |window| may be in a hierarchy that is non-activatable, in which case we - // need to cut over to the activatable hierarchy. - aura::Window* activatable = GetActivatableWindow(window); - if (!activatable) { - // There may not be a related activatable hierarchy to cut over to, in which - // case we try an unrelated one. - aura::Window* toplevel = GetToplevelWindow(window); - if (toplevel) - activatable = GetNextActivatableWindow(toplevel); - if (!activatable) - return NULL; - } - - if (!activatable->Contains(window)) { - // If there's already a child window focused in the activatable hierarchy, - // just use that (i.e. don't shift focus), otherwise we need to at least cut - // over to the activatable hierarchy. - aura::Window* focused = GetFocusedWindow(activatable); - return activatable->Contains(focused) ? focused : activatable; - } - - while (window && !CanFocusWindow(window)) - window = window->parent(); - return window; -} - -aura::Window* BaseFocusRules::GetNextActivatableWindow( - aura::Window* ignore) const { - DCHECK(ignore); - - // Can be called from the RootWindow's destruction, which has a NULL parent. - if (!ignore->parent()) - return NULL; - - // In the basic scenarios handled by BasicFocusRules, the pool of activatable - // windows is limited to the |ignore|'s siblings. - const aura::Window::Windows& siblings = ignore->parent()->children(); - DCHECK(!siblings.empty()); - - for (aura::Window::Windows::const_reverse_iterator rit = siblings.rbegin(); - rit != siblings.rend(); - ++rit) { - aura::Window* cur = *rit; - if (cur == ignore) - continue; - if (CanActivateWindow(cur)) - return cur; - } - return NULL; -} - -} // namespace corewm -} // namespace views diff --git a/chromium/ui/views/corewm/base_focus_rules.h b/chromium/ui/views/corewm/base_focus_rules.h deleted file mode 100644 index 4c564b0e798..00000000000 --- a/chromium/ui/views/corewm/base_focus_rules.h +++ /dev/null @@ -1,47 +0,0 @@ -// 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. - -#ifndef UI_VIEWS_COREWM_BASE_FOCUS_RULES_H_ -#define UI_VIEWS_COREWM_BASE_FOCUS_RULES_H_ - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "ui/views/corewm/focus_rules.h" - -namespace views { -namespace corewm { - -// A set of basic focus and activation rules. Specializations should most likely -// subclass this and call up to these methods rather than reimplementing them. -class VIEWS_EXPORT BaseFocusRules : public FocusRules { - protected: - BaseFocusRules(); - virtual ~BaseFocusRules(); - - // Returns true if the children of |window| can be activated. - virtual bool SupportsChildActivation(aura::Window* window) const = 0; - - // Returns true if |window| is considered visible for activation purposes. - virtual bool IsWindowConsideredVisibleForActivation( - aura::Window* window) const; - - // Overridden from FocusRules: - virtual bool IsToplevelWindow(aura::Window* window) const OVERRIDE; - virtual bool CanActivateWindow(aura::Window* window) const OVERRIDE; - virtual bool CanFocusWindow(aura::Window* window) const OVERRIDE; - virtual aura::Window* GetToplevelWindow(aura::Window* window) const OVERRIDE; - virtual aura::Window* GetActivatableWindow( - aura::Window* window) const OVERRIDE; - virtual aura::Window* GetFocusableWindow(aura::Window* window) const OVERRIDE; - virtual aura::Window* GetNextActivatableWindow( - aura::Window* ignore) const OVERRIDE; - - private: - DISALLOW_COPY_AND_ASSIGN(BaseFocusRules); -}; - -} // namespace corewm -} // namespace views - -#endif // UI_VIEWS_COREWM_BASE_FOCUS_RULES_H_ diff --git a/chromium/ui/views/corewm/capture_controller.cc b/chromium/ui/views/corewm/capture_controller.cc deleted file mode 100644 index 9a65e381da1..00000000000 --- a/chromium/ui/views/corewm/capture_controller.cc +++ /dev/null @@ -1,145 +0,0 @@ -// 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. - -#include "ui/views/corewm/capture_controller.h" - -#include "ui/aura/root_window.h" -#include "ui/aura/window.h" - -namespace views { -namespace corewm { - -//////////////////////////////////////////////////////////////////////////////// -// CaptureController, public: - -void CaptureController::Attach(aura::Window* root) { - DCHECK_EQ(0u, root_windows_.count(root)); - root_windows_.insert(root); - aura::client::SetCaptureClient(root, this); -} - -void CaptureController::Detach(aura::Window* root) { - root_windows_.erase(root); - aura::client::SetCaptureClient(root, NULL); -} - -//////////////////////////////////////////////////////////////////////////////// -// CaptureController, aura::client::CaptureClient implementation: - -void CaptureController::SetCapture(aura::Window* new_capture_window) { - if (capture_window_ == new_capture_window) - return; - - // Make sure window has a root window. - DCHECK(!new_capture_window || new_capture_window->GetRootWindow()); - DCHECK(!capture_window_ || capture_window_->GetRootWindow()); - - aura::Window* old_capture_window = capture_window_; - aura::Window* old_capture_root = old_capture_window ? - old_capture_window->GetRootWindow() : NULL; - - // Copy the list in case it's modified out from under us. - RootWindows root_windows(root_windows_); - - // If we're actually starting capture, then cancel any touches/gestures - // that aren't already locked to the new window, and transfer any on the - // old capture window to the new one. When capture is released we have no - // distinction between the touches/gestures that were in the window all - // along (and so shouldn't be canceled) and those that got moved, so - // just leave them all where they are. - if (new_capture_window) { - ui::GestureRecognizer::Get()->TransferEventsTo(old_capture_window, - new_capture_window); - } - - capture_window_ = new_capture_window; - - for (RootWindows::const_iterator i = root_windows.begin(); - i != root_windows.end(); ++i) { - aura::client::CaptureDelegate* delegate = (*i)->GetDispatcher(); - delegate->UpdateCapture(old_capture_window, new_capture_window); - } - - aura::Window* capture_root = - capture_window_ ? capture_window_->GetRootWindow() : NULL; - if (capture_root != old_capture_root) { - if (old_capture_root) { - aura::client::CaptureDelegate* delegate = - old_capture_root->GetDispatcher(); - delegate->ReleaseNativeCapture(); - } - if (capture_root) { - aura::client::CaptureDelegate* delegate = capture_root->GetDispatcher(); - delegate->SetNativeCapture(); - } - } -} - -void CaptureController::ReleaseCapture(aura::Window* window) { - if (capture_window_ != window) - return; - SetCapture(NULL); -} - -aura::Window* CaptureController::GetCaptureWindow() { - return capture_window_; -} - -aura::Window* CaptureController::GetGlobalCaptureWindow() { - return capture_window_; -} - -//////////////////////////////////////////////////////////////////////////////// -// CaptureController, private: - -CaptureController::CaptureController() - : capture_window_(NULL) { -} - -CaptureController::~CaptureController() { -} - -//////////////////////////////////////////////////////////////////////////////// -// ScopedCaptureClient: - -// static -CaptureController* ScopedCaptureClient::capture_controller_ = NULL; - -ScopedCaptureClient::ScopedCaptureClient(aura::Window* root) - : root_window_(root) { - root->AddObserver(this); - if (!capture_controller_) - capture_controller_ = new CaptureController; - capture_controller_->Attach(root); -} - -ScopedCaptureClient::~ScopedCaptureClient() { - Shutdown(); -} - -// static -bool ScopedCaptureClient::IsActive() { - return capture_controller_ && capture_controller_->is_active(); -} - -void ScopedCaptureClient::OnWindowDestroyed(aura::Window* window) { - DCHECK_EQ(window, root_window_); - Shutdown(); -} - -void ScopedCaptureClient::Shutdown() { - if (!root_window_) - return; - - root_window_->RemoveObserver(this); - capture_controller_->Detach(root_window_); - if (!capture_controller_->is_active()) { - delete capture_controller_; - capture_controller_ = NULL; - } - root_window_ = NULL; -} - -} // namespace corewm -} // namespace views diff --git a/chromium/ui/views/corewm/capture_controller.h b/chromium/ui/views/corewm/capture_controller.h deleted file mode 100644 index e7d1ffd6eca..00000000000 --- a/chromium/ui/views/corewm/capture_controller.h +++ /dev/null @@ -1,88 +0,0 @@ -// 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. - -#ifndef UI_VIEWS_COREWM_CAPTURE_CONTROLLER_H_ -#define UI_VIEWS_COREWM_CAPTURE_CONTROLLER_H_ - -#include <set> - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "ui/aura/client/capture_client.h" -#include "ui/aura/window_observer.h" -#include "ui/views/views_export.h" - -namespace views { -namespace corewm { - -// Internal CaptureClient implementation. See ScopedCaptureClient for details. -class VIEWS_EXPORT CaptureController : public aura::client::CaptureClient { - public: - // Adds |root| to the list of RootWindows notified when capture changes. - void Attach(aura::Window* root); - - // Removes |root| from the list of RootWindows notified when capture changes. - void Detach(aura::Window* root); - - // Returns true if this CaptureController is installed on at least one - // RootWindow. - bool is_active() const { return !root_windows_.empty(); } - - // Overridden from aura::client::CaptureClient: - virtual void SetCapture(aura::Window* window) OVERRIDE; - virtual void ReleaseCapture(aura::Window* window) OVERRIDE; - virtual aura::Window* GetCaptureWindow() OVERRIDE; - virtual aura::Window* GetGlobalCaptureWindow() OVERRIDE; - - private: - friend class ScopedCaptureClient; - typedef std::set<aura::Window*> RootWindows; - - CaptureController(); - virtual ~CaptureController(); - - // The current capture window. NULL if there is no capture window. - aura::Window* capture_window_; - - // Set of RootWindows notified when capture changes. - RootWindows root_windows_; - - DISALLOW_COPY_AND_ASSIGN(CaptureController); -}; - -// ScopedCaptureClient is responsible for creating a CaptureClient for a -// RootWindow. Specifically it creates a single CaptureController that is shared -// among all ScopedCaptureClients and adds the RootWindow to it. -class VIEWS_EXPORT ScopedCaptureClient : public aura::WindowObserver { - public: - explicit ScopedCaptureClient(aura::Window* root); - virtual ~ScopedCaptureClient(); - - // Returns true if there is a CaptureController with at least one RootWindow. - static bool IsActive(); - - aura::client::CaptureClient* capture_client() { - return capture_controller_; - } - - // Overridden from aura::WindowObserver: - virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE; - - private: - // Invoked from destructor and OnWindowDestroyed() to cleanup. - void Shutdown(); - - // The single CaptureController instance. - static CaptureController* capture_controller_; - - // RootWindow this ScopedCaptureClient was create for. - aura::Window* root_window_; - - DISALLOW_COPY_AND_ASSIGN(ScopedCaptureClient); -}; - -} // namespace corewm -} // namespace views - -#endif // UI_VIEWS_COREWM_CAPTURE_CONTROLLER_H_ diff --git a/chromium/ui/views/corewm/capture_controller_unittest.cc b/chromium/ui/views/corewm/capture_controller_unittest.cc index 558a4030f51..ffece4a89ab 100644 --- a/chromium/ui/views/corewm/capture_controller_unittest.cc +++ b/chromium/ui/views/corewm/capture_controller_unittest.cc @@ -2,16 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/views/corewm/capture_controller.h" +#include "ui/wm/core/capture_controller.h" #include "base/logging.h" #include "ui/aura/env.h" -#include "ui/aura/root_window.h" #include "ui/aura/test/aura_test_base.h" #include "ui/aura/test/event_generator.h" #include "ui/aura/test/test_screen.h" #include "ui/aura/test/test_window_delegate.h" #include "ui/aura/window.h" +#include "ui/aura/window_event_dispatcher.h" #include "ui/events/event.h" #include "ui/events/event_utils.h" #include "ui/views/test/views_test_base.h" @@ -32,25 +32,21 @@ class CaptureControllerTest : public aura::test::AuraTestBase { virtual void SetUp() OVERRIDE { AuraTestBase::SetUp(); - capture_controller_.reset(new corewm::ScopedCaptureClient(root_window())); + capture_controller_.reset(new wm::ScopedCaptureClient(root_window())); - second_root_.reset(new aura::RootWindow( - aura::RootWindow::CreateParams(gfx::Rect(0, 0, 800, 600)))); - second_root_->Init(); - second_root_->window()->Show(); - second_root_->SetHostSize(gfx::Size(800, 600)); + second_host_.reset(aura::WindowTreeHost::Create(gfx::Rect(0, 0, 800, 600))); + second_host_->InitHost(); + second_host_->window()->Show(); + second_host_->SetBounds(gfx::Rect(800, 600)); second_capture_controller_.reset( - new corewm::ScopedCaptureClient(second_root_->window())); + new wm::ScopedCaptureClient(second_host_->window())); #if !defined(OS_CHROMEOS) - desktop_position_client_.reset(new DesktopScreenPositionClient()); - aura::client::SetScreenPositionClient(root_window(), - desktop_position_client_.get()); - - second_desktop_position_client_.reset(new DesktopScreenPositionClient()); - aura::client::SetScreenPositionClient( - second_root_->window(), - second_desktop_position_client_.get()); + desktop_position_client_.reset( + new DesktopScreenPositionClient(root_window())); + + second_desktop_position_client_.reset( + new DesktopScreenPositionClient(second_host_->window())); #endif } @@ -63,7 +59,7 @@ class CaptureControllerTest : public aura::test::AuraTestBase { second_capture_controller_.reset(); // Kill any active compositors before we hit the compositor shutdown paths. - second_root_.reset(); + second_host_.reset(); #if !defined(OS_CHROMEOS) desktop_position_client_.reset(); @@ -81,9 +77,9 @@ class CaptureControllerTest : public aura::test::AuraTestBase { return second_capture_controller_->capture_client()->GetCaptureWindow(); } - scoped_ptr<corewm::ScopedCaptureClient> capture_controller_; - scoped_ptr<aura::RootWindow> second_root_; - scoped_ptr<corewm::ScopedCaptureClient> second_capture_controller_; + scoped_ptr<wm::ScopedCaptureClient> capture_controller_; + scoped_ptr<aura::WindowTreeHost> second_host_; + scoped_ptr<wm::ScopedCaptureClient> second_capture_controller_; #if !defined(OS_CHROMEOS) scoped_ptr<aura::client::ScreenPositionClient> desktop_position_client_; scoped_ptr<aura::client::ScreenPositionClient> @@ -96,50 +92,50 @@ class CaptureControllerTest : public aura::test::AuraTestBase { // Makes sure that internal details that are set on mouse down (such as // mouse_pressed_handler()) are cleared when another root window takes capture. TEST_F(CaptureControllerTest, ResetMouseEventHandlerOnCapture) { - // Create a window inside the RootWindow. + // Create a window inside the WindowEventDispatcher. scoped_ptr<aura::Window> w1(CreateNormalWindow(1, root_window(), NULL)); - // Make a synthesized mouse down event. Ensure that the RootWindow will - // dispatch further mouse events to |w1|. + // Make a synthesized mouse down event. Ensure that the WindowEventDispatcher + // will dispatch further mouse events to |w1|. ui::MouseEvent mouse_pressed_event(ui::ET_MOUSE_PRESSED, gfx::Point(5, 5), - gfx::Point(5, 5), 0); - dispatcher()->AsRootWindowHostDelegate()->OnHostMouseEvent( - &mouse_pressed_event); - EXPECT_EQ(w1.get(), dispatcher()->mouse_pressed_handler()); + gfx::Point(5, 5), 0, 0); + DispatchEventUsingWindowDispatcher(&mouse_pressed_event); + EXPECT_EQ(w1.get(), host()->dispatcher()->mouse_pressed_handler()); - // Build a window in the second RootWindow. + // Build a window in the second WindowEventDispatcher. scoped_ptr<aura::Window> w2( - CreateNormalWindow(2, second_root_->window(), NULL)); + CreateNormalWindow(2, second_host_->window(), NULL)); // The act of having the second window take capture should clear out mouse - // pressed handler in the first RootWindow. + // pressed handler in the first WindowEventDispatcher. w2->SetCapture(); - EXPECT_EQ(NULL, dispatcher()->mouse_pressed_handler()); + EXPECT_EQ(NULL, host()->dispatcher()->mouse_pressed_handler()); } // Makes sure that when one window gets capture, it forces the release on the // other. This is needed has to be handled explicitly on Linux, and is a sanity // check on Windows. TEST_F(CaptureControllerTest, ResetOtherWindowCaptureOnCapture) { - // Create a window inside the RootWindow. + // Create a window inside the WindowEventDispatcher. scoped_ptr<aura::Window> w1(CreateNormalWindow(1, root_window(), NULL)); w1->SetCapture(); // Both capture clients should return the same capture window. EXPECT_EQ(w1.get(), GetCaptureWindow()); EXPECT_EQ(w1.get(), GetSecondCaptureWindow()); - // Build a window in the second RootWindow and give it capture. Both capture - // clients should return the same capture window. + // Build a window in the second WindowEventDispatcher and give it capture. + // Both capture clients should return the same capture window. scoped_ptr<aura::Window> w2( - CreateNormalWindow(2, second_root_->window(), NULL)); + CreateNormalWindow(2, second_host_->window(), NULL)); w2->SetCapture(); EXPECT_EQ(w2.get(), GetCaptureWindow()); EXPECT_EQ(w2.get(), GetSecondCaptureWindow()); } -// Verifies the touch target for the RootWindow gets reset on releasing capture. +// Verifies the touch target for the WindowEventDispatcher gets reset on +// releasing capture. TEST_F(CaptureControllerTest, TouchTargetResetOnCaptureChange) { - // Create a window inside the RootWindow. + // Create a window inside the WindowEventDispatcher. scoped_ptr<aura::Window> w1(CreateNormalWindow(1, root_window(), NULL)); aura::test::EventGenerator event_generator1(root_window()); event_generator1.PressTouch(); @@ -148,17 +144,17 @@ TEST_F(CaptureControllerTest, TouchTargetResetOnCaptureChange) { EXPECT_EQ(w1.get(), GetCaptureWindow()); EXPECT_EQ(w1.get(), GetSecondCaptureWindow()); - // Build a window in the second RootWindow and give it capture. Both capture - // clients should return the same capture window. + // Build a window in the second WindowEventDispatcher and give it capture. + // Both capture clients should return the same capture window. scoped_ptr<aura::Window> w2( - CreateNormalWindow(2, second_root_->window(), NULL)); + CreateNormalWindow(2, second_host_->window(), NULL)); w2->SetCapture(); EXPECT_EQ(w2.get(), GetCaptureWindow()); EXPECT_EQ(w2.get(), GetSecondCaptureWindow()); // Release capture on the window. Releasing capture should reset the touch - // target of the first RootWindow (as it no longer contains the capture - // target). + // target of the first WindowEventDispatcher (as it no longer contains the + // capture target). w2->ReleaseCapture(); EXPECT_EQ(static_cast<aura::Window*>(NULL), GetCaptureWindow()); EXPECT_EQ(static_cast<aura::Window*>(NULL), GetSecondCaptureWindow()); diff --git a/chromium/ui/views/corewm/compound_event_filter.cc b/chromium/ui/views/corewm/compound_event_filter.cc deleted file mode 100644 index efeca5cad2a..00000000000 --- a/chromium/ui/views/corewm/compound_event_filter.cc +++ /dev/null @@ -1,279 +0,0 @@ -// 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. - -#include "ui/views/corewm/compound_event_filter.h" - -#include "base/containers/hash_tables.h" -#include "base/logging.h" -#include "ui/aura/client/activation_client.h" -#include "ui/aura/client/cursor_client.h" -#include "ui/aura/client/drag_drop_client.h" -#include "ui/aura/env.h" -#include "ui/aura/root_window.h" -#include "ui/aura/window.h" -#include "ui/aura/window_delegate.h" -#include "ui/aura/window_tracker.h" -#include "ui/base/hit_test.h" -#include "ui/events/event.h" - -namespace views { -namespace corewm { - -namespace { - -bool ShouldHideCursorOnKeyEvent(const ui::KeyEvent& event) { -#if defined(OS_CHROMEOS) - // All alt and control key commands are ignored. - if (event.IsAltDown() || event.IsControlDown()) - return false; - - static bool inited = false; - static base::hash_set<int32> ignored_keys; - if (!inited) { - // Modifiers. - ignored_keys.insert(ui::VKEY_SHIFT); - ignored_keys.insert(ui::VKEY_CONTROL); - ignored_keys.insert(ui::VKEY_MENU); - - // Search key == VKEY_LWIN. - ignored_keys.insert(ui::VKEY_LWIN); - - // Function keys. - for (int key = ui::VKEY_F1; key <= ui::VKEY_F24; ++key) - ignored_keys.insert(key); - - // Media keys. - for (int key = ui::VKEY_BROWSER_BACK; key <= ui::VKEY_MEDIA_LAUNCH_APP2; - ++key) { - ignored_keys.insert(key); - } - -#if defined(OS_POSIX) - ignored_keys.insert(ui::VKEY_WLAN); - ignored_keys.insert(ui::VKEY_POWER); - ignored_keys.insert(ui::VKEY_BRIGHTNESS_DOWN); - ignored_keys.insert(ui::VKEY_BRIGHTNESS_UP); - ignored_keys.insert(ui::VKEY_KBD_BRIGHTNESS_DOWN); - ignored_keys.insert(ui::VKEY_KBD_BRIGHTNESS_UP); -#endif - - inited = true; - } - - if (ignored_keys.count(event.key_code()) > 0) - return false; - - return true; -#else // !defined(OS_CHROMEOS) - return false; -#endif // defined(OS_CHROMEOS) -} - -// Returns true if the cursor should be hidden on touch events. -bool ShouldHideCursorOnTouch() { -#if defined(OS_CHROMEOS) - return true; -#else - // Not necessary on windows as windows does it for us. If we do need this - // funcionality on linux (non-chromeos) we need to make sure - // CompoundEventFilter shows on the right root (it currently doesn't always). - return false; -#endif -} - -} // namespace - -//////////////////////////////////////////////////////////////////////////////// -// CompoundEventFilter, public: - -CompoundEventFilter::CompoundEventFilter() { -} - -CompoundEventFilter::~CompoundEventFilter() { - // Additional filters are not owned by CompoundEventFilter and they - // should all be removed when running here. |handlers_| has - // check_empty == true and will DCHECK failure if it is not empty. -} - -// static -gfx::NativeCursor CompoundEventFilter::CursorForWindowComponent( - int window_component) { - switch (window_component) { - case HTBOTTOM: - return ui::kCursorSouthResize; - case HTBOTTOMLEFT: - return ui::kCursorSouthWestResize; - case HTBOTTOMRIGHT: - return ui::kCursorSouthEastResize; - case HTLEFT: - return ui::kCursorWestResize; - case HTRIGHT: - return ui::kCursorEastResize; - case HTTOP: - return ui::kCursorNorthResize; - case HTTOPLEFT: - return ui::kCursorNorthWestResize; - case HTTOPRIGHT: - return ui::kCursorNorthEastResize; - default: - return ui::kCursorNull; - } -} - -void CompoundEventFilter::AddHandler(ui::EventHandler* handler) { - handlers_.AddObserver(handler); -} - -void CompoundEventFilter::RemoveHandler(ui::EventHandler* handler) { - handlers_.RemoveObserver(handler); -} - -//////////////////////////////////////////////////////////////////////////////// -// CompoundEventFilter, private: - -void CompoundEventFilter::UpdateCursor(aura::Window* target, - ui::MouseEvent* event) { - // If drag and drop is in progress, let the drag drop client set the cursor - // instead of setting the cursor here. - aura::Window* root_window = target->GetRootWindow(); - aura::client::DragDropClient* drag_drop_client = - aura::client::GetDragDropClient(root_window); - if (drag_drop_client && drag_drop_client->IsDragDropInProgress()) - return; - - aura::client::CursorClient* cursor_client = - aura::client::GetCursorClient(root_window); - if (cursor_client) { - 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); - } - - cursor_client->SetCursor(cursor); - } -} - -void CompoundEventFilter::FilterKeyEvent(ui::KeyEvent* event) { - if (handlers_.might_have_observers()) { - ObserverListBase<ui::EventHandler>::Iterator it(handlers_); - ui::EventHandler* handler; - while (!event->stopped_propagation() && (handler = it.GetNext()) != NULL) - handler->OnKeyEvent(event); - } -} - -void CompoundEventFilter::FilterMouseEvent(ui::MouseEvent* event) { - if (handlers_.might_have_observers()) { - ObserverListBase<ui::EventHandler>::Iterator it(handlers_); - ui::EventHandler* handler; - while (!event->stopped_propagation() && (handler = it.GetNext()) != NULL) - handler->OnMouseEvent(event); - } -} - -void CompoundEventFilter::FilterTouchEvent(ui::TouchEvent* event) { - if (handlers_.might_have_observers()) { - ObserverListBase<ui::EventHandler>::Iterator it(handlers_); - ui::EventHandler* handler; - while (!event->stopped_propagation() && (handler = it.GetNext()) != NULL) - handler->OnTouchEvent(event); - } -} - -void CompoundEventFilter::SetCursorVisibilityOnEvent(aura::Window* target, - ui::Event* event, - bool show) { - if (event->flags() & ui::EF_IS_SYNTHESIZED) - return; - - aura::client::CursorClient* client = - aura::client::GetCursorClient(target->GetRootWindow()); - if (!client) - return; - - if (show) - client->ShowCursor(); - else - client->HideCursor(); -} - -void CompoundEventFilter::SetMouseEventsEnableStateOnEvent(aura::Window* target, - ui::Event* event, - bool enable) { - if (event->flags() & ui::EF_IS_SYNTHESIZED) - return; - aura::client::CursorClient* client = - aura::client::GetCursorClient(target->GetRootWindow()); - if (!client) - return; - - if (enable) - client->EnableMouseEvents(); - else - client->DisableMouseEvents(); -} - -//////////////////////////////////////////////////////////////////////////////// -// CompoundEventFilter, ui::EventHandler implementation: - -void CompoundEventFilter::OnKeyEvent(ui::KeyEvent* event) { - if (ShouldHideCursorOnKeyEvent(*event)) { - SetCursorVisibilityOnEvent( - static_cast<aura::Window*>(event->target()), event, false); - } - - FilterKeyEvent(event); -} - -void CompoundEventFilter::OnMouseEvent(ui::MouseEvent* event) { - aura::Window* window = static_cast<aura::Window*>(event->target()); - aura::WindowTracker window_tracker; - window_tracker.Add(window); - - // We must always update the cursor, otherwise the cursor can get stuck if an - // event filter registered with us consumes the event. - // It should also update the cursor for clicking and wheels for ChromeOS boot. - // When ChromeOS is booted, it hides the mouse cursor but immediate mouse - // operation will show the cursor. - // We also update the cursor for mouse enter in case a mouse cursor is sent to - // outside of the root window and moved back for some reasons (e.g. running on - // on Desktop for testing, or a bug in pointer barrier). - if (event->type() == ui::ET_MOUSE_ENTERED || - event->type() == ui::ET_MOUSE_MOVED || - event->type() == ui::ET_MOUSE_PRESSED || - event->type() == ui::ET_MOUSEWHEEL) { - SetMouseEventsEnableStateOnEvent(window, event, true); - SetCursorVisibilityOnEvent(window, event, true); - UpdateCursor(window, event); - } - - FilterMouseEvent(event); -} - -void CompoundEventFilter::OnScrollEvent(ui::ScrollEvent* event) { -} - -void CompoundEventFilter::OnTouchEvent(ui::TouchEvent* event) { - FilterTouchEvent(event); - if (ShouldHideCursorOnTouch() && !event->handled() && - event->type() == ui::ET_TOUCH_PRESSED && - !aura::Env::GetInstance()->IsMouseButtonDown()) { - SetMouseEventsEnableStateOnEvent( - static_cast<aura::Window*>(event->target()), event, false); - } -} - -void CompoundEventFilter::OnGestureEvent(ui::GestureEvent* event) { - if (handlers_.might_have_observers()) { - ObserverListBase<ui::EventHandler>::Iterator it(handlers_); - ui::EventHandler* handler; - while (!event->stopped_propagation() && (handler = it.GetNext()) != NULL) - handler->OnGestureEvent(event); - } -} - -} // namespace corewm -} // namespace views diff --git a/chromium/ui/views/corewm/compound_event_filter.h b/chromium/ui/views/corewm/compound_event_filter.h deleted file mode 100644 index 7f724c35e06..00000000000 --- a/chromium/ui/views/corewm/compound_event_filter.h +++ /dev/null @@ -1,93 +0,0 @@ -// 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. - -#ifndef UI_VIEWS_COREWM_COMPOUND_EVENT_FILTER_H_ -#define UI_VIEWS_COREWM_COMPOUND_EVENT_FILTER_H_ - -#include "base/compiler_specific.h" -#include "base/observer_list.h" -#include "ui/events/event.h" -#include "ui/events/event_handler.h" -#include "ui/gfx/native_widget_types.h" -#include "ui/views/views_export.h" - -namespace aura { -class CursorManager; -class RootWindow; -} - -namespace ui { -class GestureEvent; -class KeyEvent; -class LocatedEvent; -class MouseEvent; -class TouchEvent; -} - -namespace views { -namespace corewm { - -// CompoundEventFilter gets all events first and can provide actions to those -// events. It implements global features such as click to activate a window and -// cursor change when moving mouse. -// Additional event filters can be added to CompoundEventFilter. Events will -// pass through those additional filters in their addition order and could be -// consumed by any of those filters. If an event is consumed by a filter, the -// rest of the filter(s) and CompoundEventFilter will not see the consumed -// event. -class VIEWS_EXPORT CompoundEventFilter : public ui::EventHandler { - public: - CompoundEventFilter(); - virtual ~CompoundEventFilter(); - - // Returns the cursor for the specified component. - static gfx::NativeCursor CursorForWindowComponent(int window_component); - - // Adds/removes additional event filters. This does not take ownership of - // the EventHandler. - // NOTE: These handlers are deprecated. Use env::AddPreTargetEventHandler etc. - // instead. - void AddHandler(ui::EventHandler* filter); - void RemoveHandler(ui::EventHandler* filter); - - private: - // Updates the cursor if the target provides a custom one, and provides - // default resize cursors for window edges. - void UpdateCursor(aura::Window* target, ui::MouseEvent* event); - - // Dispatches event to additional filters. - void FilterKeyEvent(ui::KeyEvent* event); - void FilterMouseEvent(ui::MouseEvent* event); - void FilterTouchEvent(ui::TouchEvent* event); - - // Sets the visibility of the cursor if the event is not synthesized. - void SetCursorVisibilityOnEvent(aura::Window* target, - ui::Event* event, - bool show); - - // Enables or disables mouse events if the event is not synthesized. - void SetMouseEventsEnableStateOnEvent(aura::Window* target, - ui::Event* event, - bool enable); - - // Overridden from ui::EventHandler: - virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE; - virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE; - virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE; - virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE; - virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE; - - // Additional pre-target event handlers. - ObserverList<ui::EventHandler, true> handlers_; - - // True if the cursur was hidden by the filter. - bool cursor_hidden_by_filter_; - - DISALLOW_COPY_AND_ASSIGN(CompoundEventFilter); -}; - -} // namespace corewm -} // namespace views - -#endif // UI_VIEWS_COREWM_COMPOUND_EVENT_FILTER_H_ diff --git a/chromium/ui/views/corewm/compound_event_filter_unittest.cc b/chromium/ui/views/corewm/compound_event_filter_unittest.cc deleted file mode 100644 index 6b852e4cd55..00000000000 --- a/chromium/ui/views/corewm/compound_event_filter_unittest.cc +++ /dev/null @@ -1,205 +0,0 @@ -// 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. - -#include "ui/views/corewm/compound_event_filter.h" - -#include "ui/aura/client/activation_client.h" -#include "ui/aura/client/cursor_client.h" -#include "ui/aura/env.h" -#include "ui/aura/root_window.h" -#include "ui/aura/test/aura_test_base.h" -#include "ui/aura/test/event_generator.h" -#include "ui/aura/test/test_cursor_client.h" -#include "ui/aura/test/test_windows.h" -#include "ui/aura/window.h" -#include "ui/events/event.h" -#include "ui/events/event_utils.h" - -namespace { - -#if defined(OS_CHROMEOS) -base::TimeDelta GetTime() { - return ui::EventTimeForNow(); -} -#endif // defined(OS_CHROMEOS) - -} - -namespace views { -namespace corewm { - -namespace { - -// An event filter that consumes all gesture events. -class ConsumeGestureEventFilter : public ui::EventHandler { - public: - ConsumeGestureEventFilter() {} - virtual ~ConsumeGestureEventFilter() {} - - private: - // Overridden from ui::EventHandler: - virtual void OnGestureEvent(ui::GestureEvent* e) OVERRIDE { - e->StopPropagation(); - } - - DISALLOW_COPY_AND_ASSIGN(ConsumeGestureEventFilter); -}; - -} // namespace - -typedef aura::test::AuraTestBase CompoundEventFilterTest; - -#if defined(OS_CHROMEOS) -// A keypress only hides the cursor on ChromeOS (crbug.com/304296). -TEST_F(CompoundEventFilterTest, CursorVisibilityChange) { - scoped_ptr<CompoundEventFilter> compound_filter(new CompoundEventFilter); - aura::Env::GetInstance()->AddPreTargetHandler(compound_filter.get()); - aura::test::TestWindowDelegate delegate; - scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(&delegate, 1234, - gfx::Rect(5, 5, 100, 100), root_window())); - window->Show(); - window->SetCapture(); - - aura::test::TestCursorClient cursor_client(root_window()); - - // Send key event to hide the cursor. - ui::KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_A, 0, true); - dispatcher()->AsRootWindowHostDelegate()->OnHostKeyEvent(&key); - EXPECT_FALSE(cursor_client.IsCursorVisible()); - - // Synthesized mouse event should not show the cursor. - ui::MouseEvent enter(ui::ET_MOUSE_ENTERED, gfx::Point(10, 10), - gfx::Point(10, 10), 0); - enter.set_flags(enter.flags() | ui::EF_IS_SYNTHESIZED); - dispatcher()->AsRootWindowHostDelegate()->OnHostMouseEvent(&enter); - EXPECT_FALSE(cursor_client.IsCursorVisible()); - - ui::MouseEvent move(ui::ET_MOUSE_MOVED, gfx::Point(10, 10), - gfx::Point(10, 10), 0); - move.set_flags(enter.flags() | ui::EF_IS_SYNTHESIZED); - dispatcher()->AsRootWindowHostDelegate()->OnHostMouseEvent(&move); - EXPECT_FALSE(cursor_client.IsCursorVisible()); - - ui::MouseEvent real_move(ui::ET_MOUSE_MOVED, gfx::Point(10, 10), - gfx::Point(10, 10), 0); - dispatcher()->AsRootWindowHostDelegate()->OnHostMouseEvent(&real_move); - EXPECT_TRUE(cursor_client.IsCursorVisible()); - - // Send key event to hide the cursor again. - dispatcher()->AsRootWindowHostDelegate()->OnHostKeyEvent(&key); - EXPECT_FALSE(cursor_client.IsCursorVisible()); - - // Mouse synthesized exit event should not show the cursor. - ui::MouseEvent exit(ui::ET_MOUSE_EXITED, gfx::Point(10, 10), - gfx::Point(10, 10), 0); - exit.set_flags(enter.flags() | ui::EF_IS_SYNTHESIZED); - dispatcher()->AsRootWindowHostDelegate()->OnHostMouseEvent(&exit); - EXPECT_FALSE(cursor_client.IsCursorVisible()); -} - -TEST_F(CompoundEventFilterTest, TouchHidesCursor) { - scoped_ptr<CompoundEventFilter> compound_filter(new CompoundEventFilter); - aura::Env::GetInstance()->AddPreTargetHandler(compound_filter.get()); - aura::test::TestWindowDelegate delegate; - scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(&delegate, 1234, - gfx::Rect(5, 5, 100, 100), root_window())); - window->Show(); - window->SetCapture(); - - aura::test::TestCursorClient cursor_client(root_window()); - - ui::MouseEvent mouse0(ui::ET_MOUSE_MOVED, gfx::Point(10, 10), - gfx::Point(10, 10), 0); - dispatcher()->AsRootWindowHostDelegate()->OnHostMouseEvent(&mouse0); - EXPECT_TRUE(cursor_client.IsMouseEventsEnabled()); - - // This press is required for the GestureRecognizer to associate a target - // with kTouchId - ui::TouchEvent press0( - ui::ET_TOUCH_PRESSED, gfx::Point(90, 90), 1, GetTime()); - dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press0); - EXPECT_FALSE(cursor_client.IsMouseEventsEnabled()); - - ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(10, 10), 1, GetTime()); - dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&move); - EXPECT_FALSE(cursor_client.IsMouseEventsEnabled()); - - ui::TouchEvent release( - ui::ET_TOUCH_RELEASED, gfx::Point(10, 10), 1, GetTime()); - dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release); - EXPECT_FALSE(cursor_client.IsMouseEventsEnabled()); - - ui::MouseEvent mouse1(ui::ET_MOUSE_MOVED, gfx::Point(10, 10), - gfx::Point(10, 10), 0); - // Move the cursor again. The cursor should be visible. - dispatcher()->AsRootWindowHostDelegate()->OnHostMouseEvent(&mouse1); - EXPECT_TRUE(cursor_client.IsMouseEventsEnabled()); - - // Now activate the window and press on it again. - ui::TouchEvent press1( - ui::ET_TOUCH_PRESSED, gfx::Point(90, 90), 1, GetTime()); - aura::client::GetActivationClient( - root_window())->ActivateWindow(window.get()); - dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press1); - EXPECT_FALSE(cursor_client.IsMouseEventsEnabled()); - aura::Env::GetInstance()->RemovePreTargetHandler(compound_filter.get()); -} -#endif // defined(OS_CHROMEOS) - -// Tests that if an event filter consumes a gesture, then it doesn't focus the -// window. -TEST_F(CompoundEventFilterTest, FilterConsumedGesture) { - scoped_ptr<CompoundEventFilter> compound_filter(new CompoundEventFilter); - scoped_ptr<ui::EventHandler> gesure_handler(new ConsumeGestureEventFilter); - compound_filter->AddHandler(gesure_handler.get()); - aura::Env::GetInstance()->AddPreTargetHandler(compound_filter.get()); - aura::test::TestWindowDelegate delegate; - DCHECK(root_window()); - scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(&delegate, 1234, - gfx::Rect(5, 5, 100, 100), root_window())); - window->Show(); - - EXPECT_TRUE(window->CanFocus()); - EXPECT_FALSE(window->HasFocus()); - - // Tap on the window should not focus it since the filter will be consuming - // the gestures. - aura::test::EventGenerator generator(root_window(), gfx::Point(50, 50)); - generator.PressTouch(); - EXPECT_FALSE(window->HasFocus()); - - compound_filter->RemoveHandler(gesure_handler.get()); - aura::Env::GetInstance()->AddPreTargetHandler(compound_filter.get()); -} - -// Verifies we don't attempt to hide the mouse when the mouse is down and a -// touch event comes in. -TEST_F(CompoundEventFilterTest, DontHideWhenMouseDown) { - aura::test::EventGenerator event_generator(root_window()); - - scoped_ptr<CompoundEventFilter> compound_filter(new CompoundEventFilter); - aura::Env::GetInstance()->AddPreTargetHandler(compound_filter.get()); - aura::test::TestWindowDelegate delegate; - scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(&delegate, 1234, - gfx::Rect(5, 5, 100, 100), root_window())); - window->Show(); - - aura::test::TestCursorClient cursor_client(root_window()); - - // Move and press the mouse over the window. - event_generator.MoveMouseTo(10, 10); - EXPECT_TRUE(cursor_client.IsMouseEventsEnabled()); - event_generator.PressLeftButton(); - EXPECT_TRUE(cursor_client.IsMouseEventsEnabled()); - EXPECT_TRUE(aura::Env::GetInstance()->IsMouseButtonDown()); - - // Do a touch event. As the mouse button is down this should not disable mouse - // events. - event_generator.PressTouch(); - EXPECT_TRUE(cursor_client.IsMouseEventsEnabled()); - aura::Env::GetInstance()->RemovePreTargetHandler(compound_filter.get()); -} - -} // namespace corewm -} // namespace views diff --git a/chromium/ui/views/corewm/corewm_switches.cc b/chromium/ui/views/corewm/corewm_switches.cc deleted file mode 100644 index 8f0dd82a6a9..00000000000 --- a/chromium/ui/views/corewm/corewm_switches.cc +++ /dev/null @@ -1,21 +0,0 @@ -// 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. - -#include "ui/views/corewm/corewm_switches.h" - -#include "base/command_line.h" - -namespace views { -namespace corewm { -namespace switches { - -const char kNoDropShadows[] = "aura-no-shadows"; - -// If present animations are disabled. -const char kWindowAnimationsDisabled[] = - "views-corewm-window-animations-disabled"; - -} // namespace switches -} // namespace corewm -} // namespace views diff --git a/chromium/ui/views/corewm/corewm_switches.h b/chromium/ui/views/corewm/corewm_switches.h deleted file mode 100644 index 63c5251745d..00000000000 --- a/chromium/ui/views/corewm/corewm_switches.h +++ /dev/null @@ -1,27 +0,0 @@ -// 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. - -#ifndef UI_VIEWS_COREWM_COREWM_SWITCHES_H_ -#define UI_VIEWS_COREWM_COREWM_SWITCHES_H_ - -#include "build/build_config.h" -#include "ui/views/views_export.h" - -namespace views { -namespace corewm { -namespace switches { - -// Note: If you add a switch, consider if it needs to be copied to a subsequent -// command line if the process executes a new copy of itself. (For example, -// see chromeos::LoginUtil::GetOffTheRecordCommandLine().) - -// Please keep alphabetized. -VIEWS_EXPORT extern const char kNoDropShadows[]; -VIEWS_EXPORT extern const char kWindowAnimationsDisabled[]; - -} // namespace switches -} // namespace corewm -} // namespace views - -#endif // UI_VIEWS_COREWM_COREWM_SWITCHES_H_ diff --git a/chromium/ui/views/corewm/cursor_height_provider_win.cc b/chromium/ui/views/corewm/cursor_height_provider_win.cc new file mode 100644 index 00000000000..97ed7a3465e --- /dev/null +++ b/chromium/ui/views/corewm/cursor_height_provider_win.cc @@ -0,0 +1,146 @@ +// Copyright 2014 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/views/corewm/cursor_height_provider_win.h" + +#include <windows.h> +#include <algorithm> +#include <map> + +#include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" +#include "base/win/scoped_hdc.h" + +namespace { +typedef scoped_ptr<uint32_t> PixelData; +typedef std::map<HCURSOR, int> HeightStorage; + +const uint32_t kBitsPeruint32 = sizeof(uint32_t) * 8; +// All bits are 1 for transparent portion of monochromatic mask. +const uint32_t kTransparentMask = 0xffffffff; +// This is height of default pointer arrow in Windows 7. +const int kDefaultHeight = 20; +// Masks are monochromatic. +const size_t kNumberOfColors = 2; +const size_t KHeaderAndPalette = + sizeof(BITMAPINFOHEADER) + kNumberOfColors * sizeof(RGBQUAD); + +static HeightStorage* cached_heights = NULL; + +// Extracts the pixel data of provided bitmap +PixelData GetBitmapData(HBITMAP handle, const BITMAPINFO& info, HDC hdc) { + PixelData data; + // Masks are monochromatic. + DCHECK_EQ(info.bmiHeader.biBitCount, 1); + if (info.bmiHeader.biBitCount != 1) + return data.Pass(); + + // When getting pixel data palette is appended to memory pointed by + // BITMAPINFO passed so allocate additional memory to store additional data. + scoped_ptr<BITMAPINFO> header( + reinterpret_cast<BITMAPINFO*>(new char[KHeaderAndPalette])); + memcpy(header.get(), &(info.bmiHeader), sizeof(info.bmiHeader)); + + data.reset(new uint32_t[info.bmiHeader.biSizeImage / sizeof(uint32_t)]); + + int result = GetDIBits(hdc, + handle, + 0, + info.bmiHeader.biHeight, + data.get(), + header.get(), + DIB_RGB_COLORS); + + if (result == 0) + data.reset(); + + return data.Pass(); +} + +// Checks if the specifed row is transparent in provided bitmap. +bool IsRowTransparent(const PixelData& data, + const uint32_t row_size, + const uint32_t last_byte_mask, + const uint32_t y) { + // Set the padding bits to 1 to make mask matching easier. + *(data.get() + (y + 1) * row_size - 1) |= last_byte_mask; + for (uint32_t i = y * row_size; i < (y + 1) * row_size; ++i) { + if (*(data.get() + i) != kTransparentMask) + return false; + } + return true; +} + +// Gets the vertical offset between specified cursor's hotpoint and it's bottom. +// +// Gets the cursor image data and extract cursor's visible height. +// Based on that get's what should be the vertical offset between cursor's +// hot point and the tooltip. +int CalculateCursorHeight(HCURSOR cursor_handle) { + base::win::ScopedGetDC hdc(NULL); + + ICONINFO icon = {0}; + GetIconInfo(cursor_handle, &icon); + + BITMAPINFO bitmap_info = {0}; + bitmap_info.bmiHeader.biSize = sizeof(bitmap_info.bmiHeader); + if (GetDIBits(hdc, icon.hbmMask, 0, 0, NULL, &bitmap_info, DIB_RGB_COLORS) == + 0) + return kDefaultHeight; + + // Rows are padded to full DWORDs. OR with this mask will set them to 1 + // to simplify matching with |transparent_mask|. + uint32_t last_byte_mask = ~0; + const unsigned char bits_to_shift = sizeof(last_byte_mask) * 8 - + (bitmap_info.bmiHeader.biWidth % kBitsPeruint32); + if (bits_to_shift != kBitsPeruint32) + last_byte_mask = (last_byte_mask << bits_to_shift); + else + last_byte_mask = 0; + + const uint32_t row_size = + (bitmap_info.bmiHeader.biWidth + kBitsPeruint32 - 1) / kBitsPeruint32; + PixelData data(GetBitmapData(icon.hbmMask, bitmap_info, hdc)); + if (data == NULL) + return kDefaultHeight; + + const int cursor_height = GetSystemMetrics(SM_CYCURSOR); + // Crash data seems to indicate cursor_height may be bigger than the bitmap. + int i = std::max(0, static_cast<int>(bitmap_info.bmiHeader.biHeight) - + cursor_height); + for (; i < bitmap_info.bmiHeader.biHeight; ++i) { + if (!IsRowTransparent(data, row_size, last_byte_mask, i)) { + i--; + break; + } + } + return bitmap_info.bmiHeader.biHeight - i - icon.yHotspot; +} + +} // namespace + +namespace views { +namespace corewm { + +int GetCurrentCursorVisibleHeight() { + CURSORINFO cursor = {0}; + cursor.cbSize = sizeof(cursor); + GetCursorInfo(&cursor); + + if (cached_heights == NULL) + cached_heights = new HeightStorage; + + HeightStorage::const_iterator cached_height = + cached_heights->find(cursor.hCursor); + if (cached_height != cached_heights->end()) + return cached_height->second; + + const int height = CalculateCursorHeight(cursor.hCursor); + (*cached_heights)[cursor.hCursor] = height; + + return height; +} + +} // namespace corewm +} // namespace views diff --git a/chromium/ui/views/corewm/cursor_height_provider_win.h b/chromium/ui/views/corewm/cursor_height_provider_win.h new file mode 100644 index 00000000000..c93134491f2 --- /dev/null +++ b/chromium/ui/views/corewm/cursor_height_provider_win.h @@ -0,0 +1,21 @@ +// Copyright 2014 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_VIEWS_COREWM_CURSOR_HEIGHT_PROVIDER_WIN_H_ +#define UI_VIEWS_COREWM_CURSOR_HEIGHT_PROVIDER_WIN_H_ + +namespace views { +namespace corewm { + +// Gets the visible height of current cursor. +// +// The height is offset between cursor's hot point and it's +// bottom edge, derived from first non-transparent row of cursor's mask. + +int GetCurrentCursorVisibleHeight(); + +} // namespace corewm +} // namespace views + +#endif // UI_VIEWS_COREWM_CURSOR_HEIGHT_PROVIDER_WIN_H_ diff --git a/chromium/ui/views/corewm/cursor_manager.cc b/chromium/ui/views/corewm/cursor_manager.cc deleted file mode 100644 index 2335fdd1cbf..00000000000 --- a/chromium/ui/views/corewm/cursor_manager.cc +++ /dev/null @@ -1,235 +0,0 @@ -// Copyright (c) 2013 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/views/corewm/cursor_manager.h" - -#include "base/logging.h" -#include "ui/aura/client/cursor_client_observer.h" -#include "ui/views/corewm/native_cursor_manager.h" -#include "ui/views/corewm/native_cursor_manager_delegate.h" - -namespace views { -namespace corewm { - -namespace internal { - -// Represents the cursor state which is composed of cursor type, visibility, and -// mouse events enable state. When mouse events are disabled, the cursor is -// always invisible. -class CursorState { - public: - CursorState() - : cursor_(ui::kCursorNone), - visible_(true), - scale_(1.f), - cursor_set_(ui::CURSOR_SET_NORMAL), - mouse_events_enabled_(true), - visible_on_mouse_events_enabled_(true) { - } - - gfx::NativeCursor cursor() const { return cursor_; } - void set_cursor(gfx::NativeCursor cursor) { cursor_ = cursor; } - - bool visible() const { return visible_; } - void SetVisible(bool visible) { - if (mouse_events_enabled_) - visible_ = visible; - // Ignores the call when mouse events disabled. - } - - float scale() const { return scale_; } - void set_scale(float scale) { - scale_ = scale; - } - - ui::CursorSetType cursor_set() const { return cursor_set_; } - void set_cursor_set(ui::CursorSetType cursor_set) { - cursor_set_ = cursor_set; - } - - bool mouse_events_enabled() const { return mouse_events_enabled_; } - void SetMouseEventsEnabled(bool enabled) { - if (mouse_events_enabled_ == enabled) - return; - mouse_events_enabled_ = enabled; - - // Restores the visibility when mouse events are enabled. - if (enabled) { - visible_ = visible_on_mouse_events_enabled_; - } else { - visible_on_mouse_events_enabled_ = visible_; - visible_ = false; - } - } - - private: - gfx::NativeCursor cursor_; - bool visible_; - float scale_; - ui::CursorSetType cursor_set_; - bool mouse_events_enabled_; - - // The visibility to set when mouse events are enabled. - bool visible_on_mouse_events_enabled_; - - DISALLOW_COPY_AND_ASSIGN(CursorState); -}; - -} // namespace internal - -CursorManager::CursorManager(scoped_ptr<NativeCursorManager> delegate) - : delegate_(delegate.Pass()), - cursor_lock_count_(0), - current_state_(new internal::CursorState), - state_on_unlock_(new internal::CursorState) { -} - -CursorManager::~CursorManager() { -} - -void CursorManager::SetCursor(gfx::NativeCursor cursor) { - state_on_unlock_->set_cursor(cursor); - if (cursor_lock_count_ == 0 && - GetCursor() != state_on_unlock_->cursor()) { - delegate_->SetCursor(state_on_unlock_->cursor(), this); - } -} - -gfx::NativeCursor CursorManager::GetCursor() const { - return current_state_->cursor(); -} - -void CursorManager::ShowCursor() { - state_on_unlock_->SetVisible(true); - if (cursor_lock_count_ == 0 && - IsCursorVisible() != state_on_unlock_->visible()) { - delegate_->SetVisibility(state_on_unlock_->visible(), this); - FOR_EACH_OBSERVER(aura::client::CursorClientObserver, observers_, - OnCursorVisibilityChanged(true)); - } -} - -void CursorManager::HideCursor() { - state_on_unlock_->SetVisible(false); - if (cursor_lock_count_ == 0 && - IsCursorVisible() != state_on_unlock_->visible()) { - delegate_->SetVisibility(state_on_unlock_->visible(), this); - FOR_EACH_OBSERVER(aura::client::CursorClientObserver, observers_, - OnCursorVisibilityChanged(false)); - } -} - -bool CursorManager::IsCursorVisible() const { - return current_state_->visible(); -} - -void CursorManager::SetScale(float scale) { - state_on_unlock_->set_scale(scale); - if (GetScale() != state_on_unlock_->scale()) - delegate_->SetScale(state_on_unlock_->scale(), this); -} - -float CursorManager::GetScale() const { - return current_state_->scale(); -} - -void CursorManager::SetCursorSet(ui::CursorSetType cursor_set) { - state_on_unlock_->set_cursor_set(cursor_set); - if (GetCursorSet() != state_on_unlock_->cursor_set()) - delegate_->SetCursorSet(state_on_unlock_->cursor_set(), this); -} - -ui::CursorSetType CursorManager::GetCursorSet() const { - return current_state_->cursor_set(); -} - -void CursorManager::EnableMouseEvents() { - state_on_unlock_->SetMouseEventsEnabled(true); - if (cursor_lock_count_ == 0 && - IsMouseEventsEnabled() != state_on_unlock_->mouse_events_enabled()) { - delegate_->SetMouseEventsEnabled(state_on_unlock_->mouse_events_enabled(), - this); - } -} - -void CursorManager::DisableMouseEvents() { - state_on_unlock_->SetMouseEventsEnabled(false); - if (cursor_lock_count_ == 0 && - IsMouseEventsEnabled() != state_on_unlock_->mouse_events_enabled()) { - delegate_->SetMouseEventsEnabled(state_on_unlock_->mouse_events_enabled(), - this); - } -} - -bool CursorManager::IsMouseEventsEnabled() const { - return current_state_->mouse_events_enabled(); -} - -void CursorManager::SetDisplay(const gfx::Display& display) { - delegate_->SetDisplay(display, this); -} - -void CursorManager::LockCursor() { - cursor_lock_count_++; -} - -void CursorManager::UnlockCursor() { - cursor_lock_count_--; - DCHECK_GE(cursor_lock_count_, 0); - if (cursor_lock_count_ > 0) - return; - - if (GetCursor() != state_on_unlock_->cursor()) { - delegate_->SetCursor(state_on_unlock_->cursor(), this); - } - if (IsMouseEventsEnabled() != state_on_unlock_->mouse_events_enabled()) { - delegate_->SetMouseEventsEnabled(state_on_unlock_->mouse_events_enabled(), - this); - } - if (IsCursorVisible() != state_on_unlock_->visible()) { - delegate_->SetVisibility(state_on_unlock_->visible(), - this); - } -} - -bool CursorManager::IsCursorLocked() const { - return cursor_lock_count_ > 0; -} - -void CursorManager::AddObserver( - aura::client::CursorClientObserver* observer) { - observers_.AddObserver(observer); -} - -void CursorManager::RemoveObserver( - aura::client::CursorClientObserver* observer) { - observers_.RemoveObserver(observer); -} - -void CursorManager::CommitCursor(gfx::NativeCursor cursor) { - current_state_->set_cursor(cursor); -} - -void CursorManager::CommitVisibility(bool visible) { - // TODO(tdanderson): Find a better place for this so we don't - // notify the observers more than is necessary. - FOR_EACH_OBSERVER(aura::client::CursorClientObserver, observers_, - OnCursorVisibilityChanged(visible)); - current_state_->SetVisible(visible); -} - -void CursorManager::CommitScale(float scale) { - current_state_->set_scale(scale); -} - -void CursorManager::CommitCursorSet(ui::CursorSetType cursor_set) { - current_state_->set_cursor_set(cursor_set); -} - -void CursorManager::CommitMouseEventsEnabled(bool enabled) { - current_state_->SetMouseEventsEnabled(enabled); -} - -} // namespace corewm -} // namespace views diff --git a/chromium/ui/views/corewm/cursor_manager.h b/chromium/ui/views/corewm/cursor_manager.h deleted file mode 100644 index 29f890ae6bd..00000000000 --- a/chromium/ui/views/corewm/cursor_manager.h +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) 2013 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_VIEWS_COREWM_CURSOR_MANAGER_H_ -#define UI_VIEWS_COREWM_CURSOR_MANAGER_H_ - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "base/memory/scoped_ptr.h" -#include "base/observer_list.h" -#include "ui/aura/client/cursor_client.h" -#include "ui/base/cursor/cursor.h" -#include "ui/gfx/native_widget_types.h" -#include "ui/gfx/point.h" -#include "ui/views/corewm/native_cursor_manager_delegate.h" -#include "ui/views/views_export.h" - -namespace gfx { -class Display; -} - -namespace views { -namespace corewm { - -namespace internal { -class CursorState; -} - -class NativeCursorManager; - -// This class receives requests to change cursor properties, as well as -// requests to queue any further changes until a later time. It sends changes -// to the NativeCursorManager, which communicates back to us when these changes -// were made through the NativeCursorManagerDelegate interface. -class VIEWS_EXPORT CursorManager : public aura::client::CursorClient, - public NativeCursorManagerDelegate { - public: - CursorManager(scoped_ptr<NativeCursorManager> delegate); - virtual ~CursorManager(); - - // Overridden from aura::client::CursorClient: - virtual void SetCursor(gfx::NativeCursor) OVERRIDE; - virtual gfx::NativeCursor GetCursor() const OVERRIDE; - virtual void ShowCursor() OVERRIDE; - virtual void HideCursor() OVERRIDE; - virtual bool IsCursorVisible() const OVERRIDE; - virtual void SetScale(float scale) OVERRIDE; - virtual float GetScale() const OVERRIDE; - virtual void SetCursorSet(ui::CursorSetType cursor_set) OVERRIDE; - virtual ui::CursorSetType GetCursorSet() const OVERRIDE; - virtual void EnableMouseEvents() OVERRIDE; - virtual void DisableMouseEvents() OVERRIDE; - virtual bool IsMouseEventsEnabled() const OVERRIDE; - virtual void SetDisplay(const gfx::Display& display) OVERRIDE; - virtual void LockCursor() OVERRIDE; - virtual void UnlockCursor() OVERRIDE; - virtual bool IsCursorLocked() const OVERRIDE; - virtual void AddObserver( - aura::client::CursorClientObserver* observer) OVERRIDE; - virtual void RemoveObserver( - aura::client::CursorClientObserver* observer) OVERRIDE; - - private: - // Overridden from NativeCursorManagerDelegate: - virtual void CommitCursor(gfx::NativeCursor cursor) OVERRIDE; - virtual void CommitVisibility(bool visible) OVERRIDE; - virtual void CommitScale(float scale) OVERRIDE; - virtual void CommitCursorSet(ui::CursorSetType cursor_set) OVERRIDE; - virtual void CommitMouseEventsEnabled(bool enabled) OVERRIDE; - - scoped_ptr<NativeCursorManager> delegate_; - - // Number of times LockCursor() has been invoked without a corresponding - // UnlockCursor(). - int cursor_lock_count_; - - // The current state of the cursor. - scoped_ptr<internal::CursorState> current_state_; - - // The cursor state to restore when the cursor is unlocked. - scoped_ptr<internal::CursorState> state_on_unlock_; - - ObserverList<aura::client::CursorClientObserver> observers_; - - DISALLOW_COPY_AND_ASSIGN(CursorManager); -}; - -} // namespace corewm -} // namespace views - -#endif // UI_VIEWS_COREWM_CURSOR_MANAGER_H_ diff --git a/chromium/ui/views/corewm/cursor_manager_unittest.cc b/chromium/ui/views/corewm/cursor_manager_unittest.cc deleted file mode 100644 index a9c507782a5..00000000000 --- a/chromium/ui/views/corewm/cursor_manager_unittest.cc +++ /dev/null @@ -1,353 +0,0 @@ -// Copyright (c) 2013 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/views/corewm/cursor_manager.h" - -#include "ui/aura/client/cursor_client_observer.h" -#include "ui/views/corewm/native_cursor_manager.h" -#include "ui/views/test/views_test_base.h" - -namespace { - -class TestingCursorManager : public views::corewm::NativeCursorManager { - public: - // Overridden from views::corewm::NativeCursorManager: - virtual void SetDisplay( - const gfx::Display& display, - views::corewm::NativeCursorManagerDelegate* delegate) OVERRIDE {} - - virtual void SetCursor( - gfx::NativeCursor cursor, - views::corewm::NativeCursorManagerDelegate* delegate) OVERRIDE { - delegate->CommitCursor(cursor); - } - - virtual void SetVisibility( - bool visible, - views::corewm::NativeCursorManagerDelegate* delegate) OVERRIDE { - delegate->CommitVisibility(visible); - } - - virtual void SetMouseEventsEnabled( - bool enabled, - views::corewm::NativeCursorManagerDelegate* delegate) OVERRIDE { - delegate->CommitMouseEventsEnabled(enabled); - } - - virtual void SetCursorSet( - ui::CursorSetType cursor_set, - views::corewm::NativeCursorManagerDelegate* delegate) OVERRIDE { - delegate->CommitCursorSet(cursor_set); - } - - virtual void SetScale( - float scale, - views::corewm::NativeCursorManagerDelegate* delegate) OVERRIDE { - delegate->CommitScale(scale); - } -}; - -} // namespace - -class CursorManagerTest : public views::ViewsTestBase { - protected: - CursorManagerTest() - : delegate_(new TestingCursorManager), - cursor_manager_(scoped_ptr<views::corewm::NativeCursorManager>( - delegate_)) { - } - - TestingCursorManager* delegate_; - views::corewm::CursorManager cursor_manager_; -}; - -class TestingCursorClientObserver : public aura::client::CursorClientObserver { - public: - TestingCursorClientObserver() - : cursor_visibility_(false), - did_visibility_change_(false) {} - void reset() { cursor_visibility_ = did_visibility_change_ = false; } - bool is_cursor_visible() const { return cursor_visibility_; } - bool did_visibility_change() const { return did_visibility_change_; } - - // Overridden from aura::client::CursorClientObserver: - virtual void OnCursorVisibilityChanged(bool is_visible) OVERRIDE { - cursor_visibility_ = is_visible; - did_visibility_change_ = true; - } - - private: - bool cursor_visibility_; - bool did_visibility_change_; - - DISALLOW_COPY_AND_ASSIGN(TestingCursorClientObserver); -}; - -TEST_F(CursorManagerTest, ShowHideCursor) { - cursor_manager_.SetCursor(ui::kCursorCopy); - EXPECT_EQ(ui::kCursorCopy, cursor_manager_.GetCursor().native_type()); - - cursor_manager_.ShowCursor(); - EXPECT_TRUE(cursor_manager_.IsCursorVisible()); - cursor_manager_.HideCursor(); - EXPECT_FALSE(cursor_manager_.IsCursorVisible()); - // The current cursor does not change even when the cursor is not shown. - EXPECT_EQ(ui::kCursorCopy, cursor_manager_.GetCursor().native_type()); - - // Check if cursor visibility is locked. - cursor_manager_.LockCursor(); - EXPECT_FALSE(cursor_manager_.IsCursorVisible()); - cursor_manager_.ShowCursor(); - EXPECT_FALSE(cursor_manager_.IsCursorVisible()); - cursor_manager_.UnlockCursor(); - EXPECT_TRUE(cursor_manager_.IsCursorVisible()); - - cursor_manager_.LockCursor(); - EXPECT_TRUE(cursor_manager_.IsCursorVisible()); - cursor_manager_.HideCursor(); - EXPECT_TRUE(cursor_manager_.IsCursorVisible()); - cursor_manager_.UnlockCursor(); - EXPECT_FALSE(cursor_manager_.IsCursorVisible()); - - // Checks setting visiblity while cursor is locked does not affect the - // subsequent uses of UnlockCursor. - cursor_manager_.LockCursor(); - cursor_manager_.HideCursor(); - cursor_manager_.UnlockCursor(); - EXPECT_FALSE(cursor_manager_.IsCursorVisible()); - - cursor_manager_.ShowCursor(); - cursor_manager_.LockCursor(); - cursor_manager_.UnlockCursor(); - EXPECT_TRUE(cursor_manager_.IsCursorVisible()); - - cursor_manager_.LockCursor(); - cursor_manager_.ShowCursor(); - cursor_manager_.UnlockCursor(); - EXPECT_TRUE(cursor_manager_.IsCursorVisible()); - - cursor_manager_.HideCursor(); - cursor_manager_.LockCursor(); - cursor_manager_.UnlockCursor(); - EXPECT_FALSE(cursor_manager_.IsCursorVisible()); -} - -// Verifies that LockCursor/UnlockCursor work correctly with -// EnableMouseEvents and DisableMouseEvents -TEST_F(CursorManagerTest, EnableDisableMouseEvents) { - cursor_manager_.SetCursor(ui::kCursorCopy); - EXPECT_EQ(ui::kCursorCopy, cursor_manager_.GetCursor().native_type()); - - cursor_manager_.EnableMouseEvents(); - EXPECT_TRUE(cursor_manager_.IsMouseEventsEnabled()); - cursor_manager_.DisableMouseEvents(); - EXPECT_FALSE(cursor_manager_.IsMouseEventsEnabled()); - // The current cursor does not change even when the cursor is not shown. - EXPECT_EQ(ui::kCursorCopy, cursor_manager_.GetCursor().native_type()); - - // Check if cursor enable state is locked. - cursor_manager_.LockCursor(); - EXPECT_FALSE(cursor_manager_.IsMouseEventsEnabled()); - cursor_manager_.EnableMouseEvents(); - EXPECT_FALSE(cursor_manager_.IsMouseEventsEnabled()); - cursor_manager_.UnlockCursor(); - EXPECT_TRUE(cursor_manager_.IsMouseEventsEnabled()); - - cursor_manager_.LockCursor(); - EXPECT_TRUE(cursor_manager_.IsMouseEventsEnabled()); - cursor_manager_.DisableMouseEvents(); - EXPECT_TRUE(cursor_manager_.IsMouseEventsEnabled()); - cursor_manager_.UnlockCursor(); - EXPECT_FALSE(cursor_manager_.IsMouseEventsEnabled()); - - // Checks enabling cursor while cursor is locked does not affect the - // subsequent uses of UnlockCursor. - cursor_manager_.LockCursor(); - cursor_manager_.DisableMouseEvents(); - cursor_manager_.UnlockCursor(); - EXPECT_FALSE(cursor_manager_.IsMouseEventsEnabled()); - - cursor_manager_.EnableMouseEvents(); - cursor_manager_.LockCursor(); - cursor_manager_.UnlockCursor(); - EXPECT_TRUE(cursor_manager_.IsMouseEventsEnabled()); - - cursor_manager_.LockCursor(); - cursor_manager_.EnableMouseEvents(); - cursor_manager_.UnlockCursor(); - EXPECT_TRUE(cursor_manager_.IsMouseEventsEnabled()); - - cursor_manager_.DisableMouseEvents(); - cursor_manager_.LockCursor(); - cursor_manager_.UnlockCursor(); - EXPECT_FALSE(cursor_manager_.IsMouseEventsEnabled()); -} - -TEST_F(CursorManagerTest, SetCursorSet) { - EXPECT_EQ(ui::CURSOR_SET_NORMAL, cursor_manager_.GetCursorSet()); - - cursor_manager_.SetCursorSet(ui::CURSOR_SET_NORMAL); - EXPECT_EQ(ui::CURSOR_SET_NORMAL, cursor_manager_.GetCursorSet()); - - cursor_manager_.SetCursorSet(ui::CURSOR_SET_LARGE); - EXPECT_EQ(ui::CURSOR_SET_LARGE, cursor_manager_.GetCursorSet()); - - cursor_manager_.SetCursorSet(ui::CURSOR_SET_NORMAL); - EXPECT_EQ(ui::CURSOR_SET_NORMAL, cursor_manager_.GetCursorSet()); -} - -TEST_F(CursorManagerTest, SetScale) { - EXPECT_EQ(1.f, cursor_manager_.GetScale()); - cursor_manager_.SetScale(2.f); - EXPECT_EQ(2.f, cursor_manager_.GetScale()); - - // Cusror scale does change even while cursor is locked. - cursor_manager_.LockCursor(); - EXPECT_EQ(2.f, cursor_manager_.GetScale()); - cursor_manager_.SetScale(2.5f); - EXPECT_EQ(2.5f, cursor_manager_.GetScale()); - cursor_manager_.UnlockCursor(); - - EXPECT_EQ(2.5f, cursor_manager_.GetScale()); - cursor_manager_.SetScale(1.f); - EXPECT_EQ(1.f, cursor_manager_.GetScale()); -} - -TEST_F(CursorManagerTest, IsMouseEventsEnabled) { - cursor_manager_.EnableMouseEvents(); - EXPECT_TRUE(cursor_manager_.IsMouseEventsEnabled()); - cursor_manager_.DisableMouseEvents(); - EXPECT_FALSE(cursor_manager_.IsMouseEventsEnabled()); -} - -// Verifies that the mouse events enable state changes correctly when -// ShowCursor/HideCursor and EnableMouseEvents/DisableMouseEvents are used -// together. -TEST_F(CursorManagerTest, ShowAndEnable) { - // Changing the visibility of the cursor does not affect the enable state. - cursor_manager_.EnableMouseEvents(); - cursor_manager_.ShowCursor(); - EXPECT_TRUE(cursor_manager_.IsCursorVisible()); - EXPECT_TRUE(cursor_manager_.IsMouseEventsEnabled()); - cursor_manager_.HideCursor(); - EXPECT_FALSE(cursor_manager_.IsCursorVisible()); - EXPECT_TRUE(cursor_manager_.IsMouseEventsEnabled()); - cursor_manager_.ShowCursor(); - EXPECT_TRUE(cursor_manager_.IsCursorVisible()); - EXPECT_TRUE(cursor_manager_.IsMouseEventsEnabled()); - - // When mouse events are disabled, it also gets invisible. - EXPECT_TRUE(cursor_manager_.IsCursorVisible()); - cursor_manager_.DisableMouseEvents(); - EXPECT_FALSE(cursor_manager_.IsCursorVisible()); - EXPECT_FALSE(cursor_manager_.IsMouseEventsEnabled()); - - // When mouse events are enabled, it restores the visibility state. - cursor_manager_.EnableMouseEvents(); - EXPECT_TRUE(cursor_manager_.IsCursorVisible()); - EXPECT_TRUE(cursor_manager_.IsMouseEventsEnabled()); - - cursor_manager_.ShowCursor(); - cursor_manager_.DisableMouseEvents(); - EXPECT_FALSE(cursor_manager_.IsCursorVisible()); - EXPECT_FALSE(cursor_manager_.IsMouseEventsEnabled()); - cursor_manager_.EnableMouseEvents(); - EXPECT_TRUE(cursor_manager_.IsCursorVisible()); - EXPECT_TRUE(cursor_manager_.IsMouseEventsEnabled()); - - cursor_manager_.HideCursor(); - cursor_manager_.DisableMouseEvents(); - EXPECT_FALSE(cursor_manager_.IsCursorVisible()); - EXPECT_FALSE(cursor_manager_.IsMouseEventsEnabled()); - cursor_manager_.EnableMouseEvents(); - EXPECT_FALSE(cursor_manager_.IsCursorVisible()); - EXPECT_TRUE(cursor_manager_.IsMouseEventsEnabled()); - - // When mouse events are disabled, ShowCursor is ignored. - cursor_manager_.DisableMouseEvents(); - EXPECT_FALSE(cursor_manager_.IsCursorVisible()); - EXPECT_FALSE(cursor_manager_.IsMouseEventsEnabled()); - cursor_manager_.ShowCursor(); - EXPECT_FALSE(cursor_manager_.IsCursorVisible()); - EXPECT_FALSE(cursor_manager_.IsMouseEventsEnabled()); - cursor_manager_.DisableMouseEvents(); - EXPECT_FALSE(cursor_manager_.IsCursorVisible()); - EXPECT_FALSE(cursor_manager_.IsMouseEventsEnabled()); -} - -// Verifies that calling DisableMouseEvents multiple times in a row makes no -// difference compared with calling it once. -// This is a regression test for http://crbug.com/169404. -TEST_F(CursorManagerTest, MultipleDisableMouseEvents) { - cursor_manager_.DisableMouseEvents(); - cursor_manager_.DisableMouseEvents(); - cursor_manager_.EnableMouseEvents(); - cursor_manager_.LockCursor(); - cursor_manager_.UnlockCursor(); - EXPECT_TRUE(cursor_manager_.IsCursorVisible()); -} - -// Verifies that calling EnableMouseEvents multiple times in a row makes no -// difference compared with calling it once. -TEST_F(CursorManagerTest, MultipleEnableMouseEvents) { - cursor_manager_.DisableMouseEvents(); - cursor_manager_.EnableMouseEvents(); - cursor_manager_.EnableMouseEvents(); - cursor_manager_.LockCursor(); - cursor_manager_.UnlockCursor(); - EXPECT_TRUE(cursor_manager_.IsCursorVisible()); -} - -TEST_F(CursorManagerTest, TestCursorClientObserver) { - // Add two observers. Both should have OnCursorVisibilityChanged() - // invoked when the visibility of the cursor changes. - TestingCursorClientObserver observer_a; - TestingCursorClientObserver observer_b; - cursor_manager_.AddObserver(&observer_a); - cursor_manager_.AddObserver(&observer_b); - - // Initial state before any events have been sent. - observer_a.reset(); - observer_b.reset(); - EXPECT_FALSE(observer_a.did_visibility_change()); - EXPECT_FALSE(observer_b.did_visibility_change()); - EXPECT_FALSE(observer_a.is_cursor_visible()); - EXPECT_FALSE(observer_b.is_cursor_visible()); - - // Hide the cursor using HideCursor(). - cursor_manager_.HideCursor(); - EXPECT_TRUE(observer_a.did_visibility_change()); - EXPECT_TRUE(observer_b.did_visibility_change()); - EXPECT_FALSE(observer_a.is_cursor_visible()); - EXPECT_FALSE(observer_b.is_cursor_visible()); - - // Show the cursor using ShowCursor(). - observer_a.reset(); - observer_b.reset(); - cursor_manager_.ShowCursor(); - EXPECT_TRUE(observer_a.did_visibility_change()); - EXPECT_TRUE(observer_b.did_visibility_change()); - EXPECT_TRUE(observer_a.is_cursor_visible()); - EXPECT_TRUE(observer_b.is_cursor_visible()); - - // Remove observer_b. Its OnCursorVisibilityChanged() should - // not be invoked past this point. - cursor_manager_.RemoveObserver(&observer_b); - - // Hide the cursor using HideCursor(). - observer_a.reset(); - observer_b.reset(); - cursor_manager_.HideCursor(); - EXPECT_TRUE(observer_a.did_visibility_change()); - EXPECT_FALSE(observer_b.did_visibility_change()); - EXPECT_FALSE(observer_a.is_cursor_visible()); - - // Show the cursor using ShowCursor(). - observer_a.reset(); - observer_b.reset(); - cursor_manager_.ShowCursor(); - EXPECT_TRUE(observer_a.did_visibility_change()); - EXPECT_FALSE(observer_b.did_visibility_change()); - EXPECT_TRUE(observer_a.is_cursor_visible()); -} diff --git a/chromium/ui/views/corewm/desktop_capture_controller_unittest.cc b/chromium/ui/views/corewm/desktop_capture_controller_unittest.cc index c655ec8081c..8807aafdd6e 100644 --- a/chromium/ui/views/corewm/desktop_capture_controller_unittest.cc +++ b/chromium/ui/views/corewm/desktop_capture_controller_unittest.cc @@ -2,14 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/views/corewm/capture_controller.h" +#include "ui/wm/core/capture_controller.h" #include "base/logging.h" +#include "base/path_service.h" #include "ui/aura/env.h" -#include "ui/aura/root_window.h" #include "ui/aura/test/event_generator.h" #include "ui/aura/test/test_window_delegate.h" +#include "ui/aura/window_event_dispatcher.h" +#include "ui/aura/window_tree_host.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/base/ui_base_paths.h" #include "ui/events/event.h" +#include "ui/gl/gl_surface.h" #include "ui/views/test/views_test_base.h" #include "ui/views/view.h" #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h" @@ -22,7 +27,22 @@ namespace views { -typedef ViewsTestBase DesktopCaptureControllerTest; +class DesktopCaptureControllerTest : public ViewsTestBase { + public: + DesktopCaptureControllerTest() {} + virtual ~DesktopCaptureControllerTest() {} + + virtual void SetUp() OVERRIDE { + gfx::GLSurface::InitializeOneOffForTests(); + base::FilePath pak_dir; + PathService::Get(base::DIR_MODULE, &pak_dir); + base::FilePath pak_file; + pak_file = pak_dir.Append(FILE_PATH_LITERAL("ui_test.pak")); + ui::ResourceBundle::InitSharedInstanceWithPakPath(pak_file); + + ViewsTestBase::SetUp(); + } +}; // This class provides functionality to verify whether the View instance // received the gesture event. @@ -72,13 +92,16 @@ TEST_F(DesktopCaptureControllerTest, ResetMouseHandlers) { generator1.MoveMouseToCenterOf(w1->GetNativeView()); generator1.PressLeftButton(); EXPECT_FALSE(w1->HasCapture()); - aura::RootWindow* w1_root = w1->GetNativeView()->GetDispatcher(); - EXPECT_TRUE(w1_root->mouse_pressed_handler() != NULL); - EXPECT_TRUE(w1_root->mouse_moved_handler() != NULL); + aura::WindowEventDispatcher* w1_dispatcher = + w1->GetNativeView()->GetHost()->dispatcher(); + EXPECT_TRUE(w1_dispatcher->mouse_pressed_handler() != NULL); + EXPECT_TRUE(w1_dispatcher->mouse_moved_handler() != NULL); w2->SetCapture(w2->GetRootView()); EXPECT_TRUE(w2->HasCapture()); - EXPECT_TRUE(w1_root->mouse_pressed_handler() == NULL); - EXPECT_TRUE(w1_root->mouse_moved_handler() == NULL); + EXPECT_TRUE(w1_dispatcher->mouse_pressed_handler() == NULL); + EXPECT_TRUE(w1_dispatcher->mouse_moved_handler() == NULL); + w2->ReleaseCapture(); + RunPendingMessages(); } // Tests aura::Window capture and whether gesture events are sent to the window @@ -93,8 +116,8 @@ TEST_F(DesktopCaptureControllerTest, CaptureWindowInputEventTest) { scoped_ptr<Widget> widget1(new Widget()); Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); - scoped_ptr<corewm::ScopedCaptureClient> scoped_capture_client( - new corewm::ScopedCaptureClient(params.context->GetRootWindow())); + scoped_ptr<wm::ScopedCaptureClient> scoped_capture_client( + new wm::ScopedCaptureClient(params.context->GetRootWindow())); aura::client::CaptureClient* capture_client = scoped_capture_client->capture_client(); params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; @@ -103,7 +126,8 @@ TEST_F(DesktopCaptureControllerTest, CaptureWindowInputEventTest) { internal::RootView* root1 = static_cast<internal::RootView*>(widget1->GetRootView()); - desktop_position_client1.reset(new DesktopScreenPositionClient()); + desktop_position_client1.reset( + new DesktopScreenPositionClient(params.context->GetRootWindow())); aura::client::SetScreenPositionClient( widget1->GetNativeView()->GetRootWindow(), desktop_position_client1.get()); @@ -122,10 +146,12 @@ TEST_F(DesktopCaptureControllerTest, CaptureWindowInputEventTest) { internal::RootView* root2 = static_cast<internal::RootView*>(widget2->GetRootView()); - desktop_position_client2.reset(new DesktopScreenPositionClient()); + desktop_position_client2.reset( + new DesktopScreenPositionClient(params.context->GetRootWindow())); aura::client::SetScreenPositionClient( widget2->GetNativeView()->GetRootWindow(), desktop_position_client2.get()); + ui::EventDispatchDetails details; DesktopViewInputTest* v2 = new DesktopViewInputTest(); v2->SetBoundsRect(gfx::Rect(0, 0, 300, 300)); @@ -146,7 +172,10 @@ TEST_F(DesktopCaptureControllerTest, CaptureWindowInputEventTest) { base::TimeDelta(), ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS, 0.0f, 0.0f), 0); - root1->DispatchGestureEvent(&g1); + details = root1->OnEventFromSource(&g1); + EXPECT_FALSE(details.dispatcher_destroyed); + EXPECT_FALSE(details.target_destroyed); + EXPECT_TRUE(v1->received_gesture_event()); EXPECT_FALSE(v2->received_gesture_event()); v1->Reset(); @@ -158,7 +187,10 @@ TEST_F(DesktopCaptureControllerTest, CaptureWindowInputEventTest) { EXPECT_TRUE(widget2->GetNativeView()->HasCapture()); EXPECT_EQ(capture_client->GetCaptureWindow(), widget2->GetNativeView()); - root2->DispatchGestureEvent(&g1); + details = root2->OnEventFromSource(&g1); + EXPECT_FALSE(details.dispatcher_destroyed); + EXPECT_FALSE(details.target_destroyed); + EXPECT_TRUE(v2->received_gesture_event()); EXPECT_FALSE(v1->received_gesture_event()); diff --git a/chromium/ui/views/corewm/focus_controller.cc b/chromium/ui/views/corewm/focus_controller.cc deleted file mode 100644 index 17add8417fb..00000000000 --- a/chromium/ui/views/corewm/focus_controller.cc +++ /dev/null @@ -1,365 +0,0 @@ -// 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. - -#include "ui/views/corewm/focus_controller.h" - -#include "base/auto_reset.h" -#include "ui/aura/client/activation_change_observer.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/client/capture_client.h" -#include "ui/aura/client/focus_change_observer.h" -#include "ui/aura/env.h" -#include "ui/aura/window_tracker.h" -#include "ui/events/event.h" -#include "ui/views/corewm/focus_rules.h" - -namespace views { -namespace corewm { -namespace { - -// When a modal window is activated, we bring its entire transient parent chain -// to the front. This function must be called before the modal transient is -// stacked at the top to ensure correct stacking order. -void StackTransientParentsBelowModalWindow(aura::Window* window) { - if (window->GetProperty(aura::client::kModalKey) != ui::MODAL_TYPE_WINDOW) - return; - - aura::Window* transient_parent = window->transient_parent(); - while (transient_parent) { - transient_parent->parent()->StackChildAtTop(transient_parent); - transient_parent = transient_parent->transient_parent(); - } -} - -// Stack's |window|'s layer above |relative_to|'s layer. -void StackWindowLayerAbove(aura::Window* window, aura::Window* relative_to) { - // Stack |window| above the last transient child of |relative_to| that shares - // the same parent. - const aura::Window::Windows& window_transients( - relative_to->transient_children()); - for (aura::Window::Windows::const_iterator i = window_transients.begin(); - i != window_transients.end(); ++i) { - aura::Window* transient = *i; - if (transient->parent() == relative_to->parent()) - relative_to = transient; - } - if (window != relative_to) { - window->layer()->parent()->StackAbove(window->layer(), - relative_to->layer()); - } -} - -} // namespace - -//////////////////////////////////////////////////////////////////////////////// -// FocusController, public: - -FocusController::FocusController(FocusRules* rules) - : active_window_(NULL), - focused_window_(NULL), - updating_focus_(false), - updating_activation_(false), - rules_(rules), - observer_manager_(this) { - DCHECK(rules); -} - -FocusController::~FocusController() { -} - -//////////////////////////////////////////////////////////////////////////////// -// FocusController, aura::client::ActivationClient implementation: - -void FocusController::AddObserver( - aura::client::ActivationChangeObserver* observer) { - activation_observers_.AddObserver(observer); -} - -void FocusController::RemoveObserver( - aura::client::ActivationChangeObserver* observer) { - activation_observers_.RemoveObserver(observer); -} - -void FocusController::ActivateWindow(aura::Window* window) { - FocusWindow(window); -} - -void FocusController::DeactivateWindow(aura::Window* window) { - if (window) - FocusWindow(rules_->GetNextActivatableWindow(window)); -} - -aura::Window* FocusController::GetActiveWindow() { - return active_window_; -} - -aura::Window* FocusController::GetActivatableWindow(aura::Window* window) { - return rules_->GetActivatableWindow(window); -} - -aura::Window* FocusController::GetToplevelWindow(aura::Window* window) { - return rules_->GetToplevelWindow(window); -} - -bool FocusController::OnWillFocusWindow(aura::Window* window, - const ui::Event* event) { - NOTREACHED(); - return false; -} - -bool FocusController::CanActivateWindow(aura::Window* window) const { - return rules_->CanActivateWindow(window); -} - -//////////////////////////////////////////////////////////////////////////////// -// FocusController, aura::client::FocusClient implementation: - -void FocusController::AddObserver( - aura::client::FocusChangeObserver* observer) { - focus_observers_.AddObserver(observer); -} - -void FocusController::RemoveObserver( - aura::client::FocusChangeObserver* observer) { - focus_observers_.RemoveObserver(observer); -} - -void FocusController::FocusWindow(aura::Window* window) { - if (window && - (window->Contains(focused_window_) || window->Contains(active_window_))) { - return; - } - - // We should not be messing with the focus if the window has capture, unless - // no has focus. - if (window && (aura::client::GetCaptureWindow(window) == window) && - focused_window_) { - return; - } - - // Focusing a window also activates its containing activatable window. Note - // that the rules could redirect activation activation and/or focus. - aura::Window* focusable = rules_->GetFocusableWindow(window); - aura::Window* activatable = - focusable ? rules_->GetActivatableWindow(focusable) : NULL; - - // We need valid focusable/activatable windows in the event we're not clearing - // focus. "Clearing focus" is inferred by whether or not |window| passed to - // this function is non-NULL. - if (window && (!focusable || !activatable)) - return; - DCHECK((focusable && activatable) || !window); - - // Activation change observers may change the focused window. If this happens - // we must not adjust the focus below since this will clobber that change. - aura::Window* last_focused_window = focused_window_; - if (!updating_activation_) - SetActiveWindow(window, activatable); - - // If the window's ActivationChangeObserver shifted focus to a valid window, - // we don't want to focus the window we thought would be focused by default. - bool activation_changed_focus = last_focused_window != focused_window_; - if (!updating_focus_ && (!activation_changed_focus || !focused_window_)) { - if (active_window_ && focusable) - DCHECK(active_window_->Contains(focusable)); - SetFocusedWindow(focusable); - } -} - -void FocusController::ResetFocusWithinActiveWindow(aura::Window* window) { - DCHECK(window); - if (!active_window_) - return; - if (!active_window_->Contains(window)) - return; - SetFocusedWindow(window); -} - -aura::Window* FocusController::GetFocusedWindow() { - return focused_window_; -} - -//////////////////////////////////////////////////////////////////////////////// -// FocusController, ui::EventHandler implementation: -void FocusController::OnKeyEvent(ui::KeyEvent* event) { -} - -void FocusController::OnMouseEvent(ui::MouseEvent* event) { - if (event->type() == ui::ET_MOUSE_PRESSED) - WindowFocusedFromInputEvent(static_cast<aura::Window*>(event->target())); -} - -void FocusController::OnScrollEvent(ui::ScrollEvent* event) { -} - -void FocusController::OnTouchEvent(ui::TouchEvent* event) { -} - -void FocusController::OnGestureEvent(ui::GestureEvent* event) { - if (event->type() == ui::ET_GESTURE_BEGIN && - event->details().touch_points() == 1) { - WindowFocusedFromInputEvent(static_cast<aura::Window*>(event->target())); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// FocusController, aura::WindowObserver implementation: - -void FocusController::OnWindowVisibilityChanged(aura::Window* window, - bool visible) { - if (!visible) { - WindowLostFocusFromDispositionChange(window, window->parent()); - // Despite the focus change, we need to keep the window being hidden - // stacked above the new window so it stays open on top as it animates away. - aura::Window* next_window = GetActiveWindow(); - if (next_window && next_window->parent() == window->parent()) - StackWindowLayerAbove(window, next_window); - } -} - -void FocusController::OnWindowDestroying(aura::Window* window) { - WindowLostFocusFromDispositionChange(window, window->parent()); -} - -void FocusController::OnWindowHierarchyChanging( - const HierarchyChangeParams& params) { - if (params.receiver == active_window_ && - params.target->Contains(params.receiver) && (!params.new_parent || - aura::client::GetFocusClient(params.new_parent) != - aura::client::GetFocusClient(params.receiver))) { - WindowLostFocusFromDispositionChange(params.receiver, params.old_parent); - } -} - -void FocusController::OnWindowHierarchyChanged( - const HierarchyChangeParams& params) { - if (params.receiver == focused_window_ && - params.target->Contains(params.receiver) && (!params.new_parent || - aura::client::GetFocusClient(params.new_parent) != - aura::client::GetFocusClient(params.receiver))) { - WindowLostFocusFromDispositionChange(params.receiver, params.old_parent); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// FocusController, private: - -void FocusController::SetFocusedWindow(aura::Window* window) { - if (updating_focus_ || window == focused_window_) - return; - DCHECK(rules_->CanFocusWindow(window)); - if (window) - DCHECK_EQ(window, rules_->GetFocusableWindow(window)); - - base::AutoReset<bool> updating_focus(&updating_focus_, true); - aura::Window* lost_focus = focused_window_; - if (focused_window_ && observer_manager_.IsObserving(focused_window_) && - focused_window_ != active_window_) { - observer_manager_.Remove(focused_window_); - } - focused_window_ = window; - if (focused_window_ && !observer_manager_.IsObserving(focused_window_)) - observer_manager_.Add(focused_window_); - - FOR_EACH_OBSERVER(aura::client::FocusChangeObserver, - focus_observers_, - OnWindowFocused(focused_window_, lost_focus)); - aura::client::FocusChangeObserver* observer = - aura::client::GetFocusChangeObserver(lost_focus); - if (observer) - observer->OnWindowFocused(focused_window_, lost_focus); - observer = aura::client::GetFocusChangeObserver(focused_window_); - if (observer) - observer->OnWindowFocused(focused_window_, lost_focus); -} - -void FocusController::SetActiveWindow(aura::Window* requested_window, - aura::Window* window) { - if (updating_activation_) - return; - - if (window == active_window_) { - if (requested_window) { - FOR_EACH_OBSERVER(aura::client::ActivationChangeObserver, - activation_observers_, - OnAttemptToReactivateWindow(requested_window, - active_window_)); - } - return; - } - - DCHECK(rules_->CanActivateWindow(window)); - if (window) - DCHECK_EQ(window, rules_->GetActivatableWindow(window)); - - base::AutoReset<bool> updating_activation(&updating_activation_, true); - aura::Window* lost_activation = active_window_; - // Allow for the window losing activation to be deleted during dispatch. If - // it is deleted pass NULL to observers instead of a deleted window. - aura::WindowTracker window_tracker; - if (lost_activation) - window_tracker.Add(lost_activation); - if (active_window_ && observer_manager_.IsObserving(active_window_) && - focused_window_ != active_window_) { - observer_manager_.Remove(active_window_); - } - active_window_ = window; - if (active_window_ && !observer_manager_.IsObserving(active_window_)) - observer_manager_.Add(active_window_); - if (active_window_) { - StackTransientParentsBelowModalWindow(active_window_); - active_window_->parent()->StackChildAtTop(active_window_); - } - - aura::client::ActivationChangeObserver* observer = NULL; - if (window_tracker.Contains(lost_activation)) { - observer = aura::client::GetActivationChangeObserver(lost_activation); - if (observer) - observer->OnWindowActivated(active_window_, lost_activation); - } - observer = aura::client::GetActivationChangeObserver(active_window_); - if (observer) { - observer->OnWindowActivated( - active_window_, - window_tracker.Contains(lost_activation) ? lost_activation : NULL); - } - FOR_EACH_OBSERVER(aura::client::ActivationChangeObserver, - activation_observers_, - OnWindowActivated(active_window_, - window_tracker.Contains(lost_activation) ? - lost_activation : NULL)); -} - -void FocusController::WindowLostFocusFromDispositionChange( - aura::Window* window, - aura::Window* next) { - // A window's modality state will interfere with focus restoration during its - // destruction. - window->ClearProperty(aura::client::kModalKey); - // TODO(beng): See if this function can be replaced by a call to - // FocusWindow(). - // Activation adjustments are handled first in the event of a disposition - // changed. If an activation change is necessary, focus is reset as part of - // that process so there's no point in updating focus independently. - if (window == active_window_) { - aura::Window* next_activatable = rules_->GetNextActivatableWindow(window); - SetActiveWindow(NULL, next_activatable); - if (!(active_window_ && active_window_->Contains(focused_window_))) - SetFocusedWindow(next_activatable); - } else if (window->Contains(focused_window_)) { - // Active window isn't changing, but focused window might be. - SetFocusedWindow(rules_->GetFocusableWindow(next)); - } -} - -void FocusController::WindowFocusedFromInputEvent(aura::Window* window) { - // Only focus |window| if it or any of its parents can be focused. Otherwise - // FocusWindow() will focus the topmost window, which may not be the - // currently focused one. - if (rules_->CanFocusWindow(GetToplevelWindow(window))) - FocusWindow(window); -} - -} // namespace corewm -} // namespace views diff --git a/chromium/ui/views/corewm/focus_controller.h b/chromium/ui/views/corewm/focus_controller.h deleted file mode 100644 index 1dc69b78219..00000000000 --- a/chromium/ui/views/corewm/focus_controller.h +++ /dev/null @@ -1,130 +0,0 @@ -// 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. - -#ifndef UI_VIEWS_COREWM_FOCUS_CONTROLLER_H_ -#define UI_VIEWS_COREWM_FOCUS_CONTROLLER_H_ - -#include "base/compiler_specific.h" -#include "base/memory/scoped_ptr.h" -#include "base/observer_list.h" -#include "base/scoped_observer.h" -#include "ui/aura/client/activation_client.h" -#include "ui/aura/client/focus_client.h" -#include "ui/aura/window_observer.h" -#include "ui/events/event_handler.h" -#include "ui/views/views_export.h" - -namespace views { -namespace corewm { - -class FocusRules; - -// FocusController handles focus and activation changes for an environment -// encompassing one or more RootWindows. Within an environment there can be -// only one focused and one active window at a time. When focus or activation -// changes notifications are sent using the -// aura::client::Focus/ActivationChangeObserver interfaces. -// Changes to focus and activation can be from three sources: -// . the Aura Client API (implemented here in aura::client::ActivationClient). -// (The FocusController must be set as the ActivationClient implementation -// for all RootWindows). -// . input events (implemented here in ui::EventHandler). -// (The FocusController must be registered as a pre-target handler for -// the applicable environment owner, either a RootWindow or another type). -// . Window disposition changes (implemented here in aura::WindowObserver). -// (The FocusController registers itself as an observer of the active and -// focused windows). -class VIEWS_EXPORT FocusController : public aura::client::ActivationClient, - public aura::client::FocusClient, - public ui::EventHandler, - public aura::WindowObserver { - public: - // |rules| cannot be NULL. - explicit FocusController(FocusRules* rules); - virtual ~FocusController(); - - private: - // Overridden from aura::client::ActivationClient: - virtual void AddObserver( - aura::client::ActivationChangeObserver* observer) OVERRIDE; - virtual void RemoveObserver( - aura::client::ActivationChangeObserver* observer) OVERRIDE; - virtual void ActivateWindow(aura::Window* window) OVERRIDE; - virtual void DeactivateWindow(aura::Window* window) OVERRIDE; - virtual aura::Window* GetActiveWindow() OVERRIDE; - virtual aura::Window* GetActivatableWindow(aura::Window* window) OVERRIDE; - virtual aura::Window* GetToplevelWindow(aura::Window* window) OVERRIDE; - virtual bool OnWillFocusWindow(aura::Window* window, - const ui::Event* event) OVERRIDE; - virtual bool CanActivateWindow(aura::Window* window) const OVERRIDE; - - // Overridden from aura::client::FocusClient: - virtual void AddObserver( - aura::client::FocusChangeObserver* observer) OVERRIDE; - virtual void RemoveObserver( - aura::client::FocusChangeObserver* observer) OVERRIDE; - virtual void FocusWindow(aura::Window* window) OVERRIDE; - virtual void ResetFocusWithinActiveWindow(aura::Window* window) OVERRIDE; - virtual aura::Window* GetFocusedWindow() OVERRIDE; - - // Overridden from ui::EventHandler: - virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE; - virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE; - virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE; - virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE; - virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE; - - // Overridden from aura::WindowObserver: - virtual void OnWindowVisibilityChanged(aura::Window* window, - bool visible) OVERRIDE; - virtual void OnWindowDestroying(aura::Window* window) OVERRIDE; - virtual void OnWindowHierarchyChanging( - const HierarchyChangeParams& params) OVERRIDE; - virtual void OnWindowHierarchyChanged( - const HierarchyChangeParams& params) OVERRIDE; - - // Internal implementation that sets the focused window, fires events etc. - // This function must be called with a valid focusable window. - void SetFocusedWindow(aura::Window* window); - - // Internal implementation that sets the active window, fires events etc. - // This function must be called with a valid |activatable_window|. - // |requested window| refers to the window that was passed in to an external - // request (e.g. FocusWindow or ActivateWindow). It may be NULL, e.g. if - // SetActiveWindow was not called by an external request. |activatable_window| - // refers to the actual window to be activated, which may be different. - void SetActiveWindow(aura::Window* requested_window, - aura::Window* activatable_window); - - // Called when a window's disposition changed such that it and its hierarchy - // are no longer focusable/activatable. |next| is a valid window that is used - // as a starting point for finding a window to focus next based on rules. - void WindowLostFocusFromDispositionChange(aura::Window* window, - aura::Window* next); - - // Called when an attempt is made to focus or activate a window via an input - // event targeted at that window. Rules determine the best focusable window - // for the input window. - void WindowFocusedFromInputEvent(aura::Window* window); - - aura::Window* active_window_; - aura::Window* focused_window_; - - bool updating_focus_; - bool updating_activation_; - - scoped_ptr<FocusRules> rules_; - - ObserverList<aura::client::ActivationChangeObserver> activation_observers_; - ObserverList<aura::client::FocusChangeObserver> focus_observers_; - - ScopedObserver<aura::Window, aura::WindowObserver> observer_manager_; - - DISALLOW_COPY_AND_ASSIGN(FocusController); -}; - -} // namespace corewm -} // namespace views - -#endif // UI_VIEWS_COREWM_FOCUS_CONTROLLER_H_ diff --git a/chromium/ui/views/corewm/focus_controller_unittest.cc b/chromium/ui/views/corewm/focus_controller_unittest.cc deleted file mode 100644 index cfccd056c97..00000000000 --- a/chromium/ui/views/corewm/focus_controller_unittest.cc +++ /dev/null @@ -1,1110 +0,0 @@ -// 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. - -#include "ui/views/corewm/focus_controller.h" - -#include <map> - -#include "ui/aura/client/activation_change_observer.h" -#include "ui/aura/client/activation_client.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/client/default_capture_client.h" -#include "ui/aura/client/focus_change_observer.h" -#include "ui/aura/root_window.h" -#include "ui/aura/test/aura_test_base.h" -#include "ui/aura/test/event_generator.h" -#include "ui/aura/test/test_window_delegate.h" -#include "ui/aura/test/test_windows.h" -#include "ui/aura/window.h" -#include "ui/aura/window_tracker.h" -#include "ui/events/event_handler.h" -#include "ui/views/corewm/base_focus_rules.h" - -namespace views { -namespace corewm { - -class FocusNotificationObserver : public aura::client::ActivationChangeObserver, - public aura::client::FocusChangeObserver { - public: - FocusNotificationObserver() - : activation_changed_count_(0), - focus_changed_count_(0), - reactivation_count_(0), - reactivation_requested_window_(NULL), - reactivation_actual_window_(NULL) {} - virtual ~FocusNotificationObserver() {} - - void ExpectCounts(int activation_changed_count, int focus_changed_count) { - EXPECT_EQ(activation_changed_count, activation_changed_count_); - EXPECT_EQ(focus_changed_count, focus_changed_count_); - } - int reactivation_count() const { - return reactivation_count_; - } - aura::Window* reactivation_requested_window() const { - return reactivation_requested_window_; - } - aura::Window* reactivation_actual_window() const { - return reactivation_actual_window_; - } - - private: - // Overridden from aura::client::ActivationChangeObserver: - virtual void OnWindowActivated(aura::Window* gained_active, - aura::Window* lost_active) OVERRIDE { - ++activation_changed_count_; - } - virtual void OnAttemptToReactivateWindow( - aura::Window* request_active, - aura::Window* actual_active) OVERRIDE { - ++reactivation_count_; - reactivation_requested_window_ = request_active; - reactivation_actual_window_ = actual_active; - } - - // Overridden from aura::client::FocusChangeObserver: - virtual void OnWindowFocused(aura::Window* gained_focus, - aura::Window* lost_focus) OVERRIDE { - ++focus_changed_count_; - } - - int activation_changed_count_; - int focus_changed_count_; - int reactivation_count_; - aura::Window* reactivation_requested_window_; - aura::Window* reactivation_actual_window_; - - DISALLOW_COPY_AND_ASSIGN(FocusNotificationObserver); -}; - -// ActivationChangeObserver that keeps a vector of all the windows that lost -// active. -class RecordingActivationChangeObserver - : public aura::client::ActivationChangeObserver { - public: - explicit RecordingActivationChangeObserver(aura::Window* root) - : root_(root) { - aura::client::GetActivationClient(root_)->AddObserver(this); - } - virtual ~RecordingActivationChangeObserver() { - aura::client::GetActivationClient(root_)->RemoveObserver(this); - } - - // Each time we get OnWindowActivated() the |lost_active| parameter is - // added here. - const std::vector<aura::Window*>& lost() const { return lost_; } - - // Overridden from aura::client::ActivationChangeObserver: - virtual void OnWindowActivated(aura::Window* gained_active, - aura::Window* lost_active) OVERRIDE { - lost_.push_back(lost_active); - } - - private: - aura::Window* root_; - std::vector<aura::Window*> lost_; - - DISALLOW_COPY_AND_ASSIGN(RecordingActivationChangeObserver); -}; - -// ActivationChangeObserver that deletes the window losing activation. -class DeleteOnLoseActivationChangeObserver - : public aura::client::ActivationChangeObserver { - public: - explicit DeleteOnLoseActivationChangeObserver(aura::Window* window) - : root_(window->GetRootWindow()), - window_(window) { - aura::client::GetActivationClient(root_)->AddObserver(this); - } - virtual ~DeleteOnLoseActivationChangeObserver() { - aura::client::GetActivationClient(root_)->RemoveObserver(this); - } - - bool did_delete() const { return window_ == NULL; } - - // Overridden from aura::client::ActivationChangeObserver: - virtual void OnWindowActivated(aura::Window* gained_active, - aura::Window* lost_active) OVERRIDE { - if (window_ && lost_active == window_) { - window_ = NULL; - delete lost_active; - } - } - - private: - aura::Window* root_; - aura::Window* window_; - - DISALLOW_COPY_AND_ASSIGN(DeleteOnLoseActivationChangeObserver); -}; - -class ScopedFocusNotificationObserver : public FocusNotificationObserver { - public: - ScopedFocusNotificationObserver(aura::Window* root_window) - : root_window_(root_window) { - aura::client::GetActivationClient(root_window_)->AddObserver(this); - aura::client::GetFocusClient(root_window_)->AddObserver(this); - } - virtual ~ScopedFocusNotificationObserver() { - aura::client::GetActivationClient(root_window_)->RemoveObserver(this); - aura::client::GetFocusClient(root_window_)->RemoveObserver(this); - } - - private: - aura::Window* root_window_; - - DISALLOW_COPY_AND_ASSIGN(ScopedFocusNotificationObserver); -}; - -class ScopedTargetFocusNotificationObserver : public FocusNotificationObserver { - public: - ScopedTargetFocusNotificationObserver(aura::Window* root_window, int id) - : target_(root_window->GetChildById(id)) { - aura::client::SetActivationChangeObserver(target_, this); - aura::client::SetFocusChangeObserver(target_, this); - tracker_.Add(target_); - } - virtual ~ScopedTargetFocusNotificationObserver() { - if (tracker_.Contains(target_)) { - aura::client::SetActivationChangeObserver(target_, NULL); - aura::client::SetFocusChangeObserver(target_, NULL); - } - } - - private: - aura::Window* target_; - aura::WindowTracker tracker_; - - DISALLOW_COPY_AND_ASSIGN(ScopedTargetFocusNotificationObserver); -}; - -class FocusShiftingActivationObserver - : public aura::client::ActivationChangeObserver { - public: - explicit FocusShiftingActivationObserver(aura::Window* activated_window) - : activated_window_(activated_window), - shift_focus_to_(NULL) {} - virtual ~FocusShiftingActivationObserver() {} - - void set_shift_focus_to(aura::Window* shift_focus_to) { - shift_focus_to_ = shift_focus_to; - } - - private: - // Overridden from aura::client::ActivationChangeObserver: - virtual void OnWindowActivated(aura::Window* gained_active, - aura::Window* lost_active) OVERRIDE { - // Shift focus to a child. This should prevent the default focusing from - // occurring in FocusController::FocusWindow(). - if (gained_active == activated_window_) { - aura::client::FocusClient* client = - aura::client::GetFocusClient(gained_active); - client->FocusWindow(shift_focus_to_); - } - } - - aura::Window* activated_window_; - aura::Window* shift_focus_to_; - - DISALLOW_COPY_AND_ASSIGN(FocusShiftingActivationObserver); -}; - -// BaseFocusRules subclass that allows basic overrides of focus/activation to -// be tested. This is intended more as a test that the override system works at -// all, rather than as an exhaustive set of use cases, those should be covered -// in tests for those FocusRules implementations. -class TestFocusRules : public BaseFocusRules { - public: - TestFocusRules() : focus_restriction_(NULL) {} - - // Restricts focus and activation to this window and its child hierarchy. - void set_focus_restriction(aura::Window* focus_restriction) { - focus_restriction_ = focus_restriction; - } - - // Overridden from BaseFocusRules: - virtual bool SupportsChildActivation(aura::Window* window) const OVERRIDE { - // In FocusControllerTests, only the RootWindow has activatable children. - return window->GetRootWindow() == window; - } - virtual bool CanActivateWindow(aura::Window* window) const OVERRIDE { - // Restricting focus to a non-activatable child window means the activatable - // parent outside the focus restriction is activatable. - bool can_activate = - CanFocusOrActivate(window) || window->Contains(focus_restriction_); - return can_activate ? BaseFocusRules::CanActivateWindow(window) : false; - } - virtual bool CanFocusWindow(aura::Window* window) const OVERRIDE { - return CanFocusOrActivate(window) ? - BaseFocusRules::CanFocusWindow(window) : false; - } - virtual aura::Window* GetActivatableWindow( - aura::Window* window) const OVERRIDE { - return BaseFocusRules::GetActivatableWindow( - CanFocusOrActivate(window) ? window : focus_restriction_); - } - virtual aura::Window* GetFocusableWindow( - aura::Window* window) const OVERRIDE { - return BaseFocusRules::GetFocusableWindow( - CanFocusOrActivate(window) ? window : focus_restriction_); - } - virtual aura::Window* GetNextActivatableWindow( - aura::Window* ignore) const OVERRIDE { - aura::Window* next_activatable = - BaseFocusRules::GetNextActivatableWindow(ignore); - return CanFocusOrActivate(next_activatable) ? - next_activatable : GetActivatableWindow(focus_restriction_); - } - - private: - bool CanFocusOrActivate(aura::Window* window) const { - return !focus_restriction_ || focus_restriction_->Contains(window); - } - - aura::Window* focus_restriction_; - - DISALLOW_COPY_AND_ASSIGN(TestFocusRules); -}; - -// Common infrastructure shared by all FocusController test types. -class FocusControllerTestBase : public aura::test::AuraTestBase { - protected: - FocusControllerTestBase() {} - - // Overridden from aura::test::AuraTestBase: - virtual void SetUp() OVERRIDE { - // FocusController registers itself as an Env observer so it can catch all - // window initializations, including the root_window()'s, so we create it - // before allowing the base setup. - test_focus_rules_ = new TestFocusRules; - focus_controller_.reset(new FocusController(test_focus_rules_)); - aura::test::AuraTestBase::SetUp(); - root_window()->AddPreTargetHandler(focus_controller_.get()); - aura::client::SetFocusClient(root_window(), focus_controller_.get()); - aura::client::SetActivationClient(root_window(), focus_controller_.get()); - - // Hierarchy used by all tests: - // root_window - // +-- w1 - // | +-- w11 - // | +-- w12 - // +-- w2 - // | +-- w21 - // | +-- w211 - // +-- w3 - aura::Window* w1 = aura::test::CreateTestWindowWithDelegate( - aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(), 1, - gfx::Rect(0, 0, 50, 50), root_window()); - aura::test::CreateTestWindowWithDelegate( - aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(), 11, - gfx::Rect(5, 5, 10, 10), w1); - aura::test::CreateTestWindowWithDelegate( - aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(), 12, - gfx::Rect(15, 15, 10, 10), w1); - aura::Window* w2 = aura::test::CreateTestWindowWithDelegate( - aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(), 2, - gfx::Rect(75, 75, 50, 50), root_window()); - aura::Window* w21 = aura::test::CreateTestWindowWithDelegate( - aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(), 21, - gfx::Rect(5, 5, 10, 10), w2); - aura::test::CreateTestWindowWithDelegate( - aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(), 211, - gfx::Rect(1, 1, 5, 5), w21); - aura::test::CreateTestWindowWithDelegate( - aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(), 3, - gfx::Rect(125, 125, 50, 50), root_window()); - } - virtual void TearDown() OVERRIDE { - root_window()->RemovePreTargetHandler(focus_controller_.get()); - aura::test::AuraTestBase::TearDown(); - test_focus_rules_ = NULL; // Owned by FocusController. - focus_controller_.reset(); - } - - void FocusWindow(aura::Window* window) { - aura::client::GetFocusClient(root_window())->FocusWindow(window); - } - aura::Window* GetFocusedWindow() { - return aura::client::GetFocusClient(root_window())->GetFocusedWindow(); - } - int GetFocusedWindowId() { - aura::Window* focused_window = GetFocusedWindow(); - return focused_window ? focused_window->id() : -1; - } - void ActivateWindow(aura::Window* window) { - aura::client::GetActivationClient(root_window())->ActivateWindow(window); - } - void DeactivateWindow(aura::Window* window) { - aura::client::GetActivationClient(root_window())->DeactivateWindow(window); - } - aura::Window* GetActiveWindow() { - return aura::client::GetActivationClient(root_window())->GetActiveWindow(); - } - int GetActiveWindowId() { - aura::Window* active_window = GetActiveWindow(); - return active_window ? active_window->id() : -1; - } - - TestFocusRules* test_focus_rules() { return test_focus_rules_; } - - // Test functions. - virtual void BasicFocus() = 0; - virtual void BasicActivation() = 0; - virtual void FocusEvents() = 0; - virtual void DuplicateFocusEvents() {} - virtual void ActivationEvents() = 0; - virtual void ReactivationEvents() {} - virtual void DuplicateActivationEvents() {} - virtual void ShiftFocusWithinActiveWindow() {} - virtual void ShiftFocusToChildOfInactiveWindow() {} - virtual void ShiftFocusToParentOfFocusedWindow() {} - virtual void FocusRulesOverride() = 0; - virtual void ActivationRulesOverride() = 0; - virtual void ShiftFocusOnActivation() {} - virtual void ShiftFocusOnActivationDueToHide() {} - virtual void NoShiftActiveOnActivation() {} - virtual void NoFocusChangeOnClickOnCaptureWindow() {} - virtual void ChangeFocusWhenNothingFocusedAndCaptured() {} - virtual void DontPassDeletedWindow() {} - - private: - scoped_ptr<FocusController> focus_controller_; - TestFocusRules* test_focus_rules_; - - DISALLOW_COPY_AND_ASSIGN(FocusControllerTestBase); -}; - -// Test base for tests where focus is directly set to a target window. -class FocusControllerDirectTestBase : public FocusControllerTestBase { - protected: - FocusControllerDirectTestBase() {} - - // Different test types shift focus in different ways. - virtual void FocusWindowDirect(aura::Window* window) = 0; - virtual void ActivateWindowDirect(aura::Window* window) = 0; - virtual void DeactivateWindowDirect(aura::Window* window) = 0; - - // Input events do not change focus if the window can not be focused. - virtual bool IsInputEvent() = 0; - - void FocusWindowById(int id) { - aura::Window* window = root_window()->GetChildById(id); - DCHECK(window); - FocusWindowDirect(window); - } - void ActivateWindowById(int id) { - aura::Window* window = root_window()->GetChildById(id); - DCHECK(window); - ActivateWindowDirect(window); - } - - // Overridden from FocusControllerTestBase: - virtual void BasicFocus() OVERRIDE { - EXPECT_EQ(NULL, GetFocusedWindow()); - FocusWindowById(1); - EXPECT_EQ(1, GetFocusedWindowId()); - FocusWindowById(2); - EXPECT_EQ(2, GetFocusedWindowId()); - } - virtual void BasicActivation() OVERRIDE { - EXPECT_EQ(NULL, GetActiveWindow()); - ActivateWindowById(1); - EXPECT_EQ(1, GetActiveWindowId()); - ActivateWindowById(2); - EXPECT_EQ(2, GetActiveWindowId()); - // Verify that attempting to deactivate NULL does not crash and does not - // change activation. - DeactivateWindow(NULL); - EXPECT_EQ(2, GetActiveWindowId()); - DeactivateWindow(GetActiveWindow()); - EXPECT_EQ(1, GetActiveWindowId()); - } - virtual void FocusEvents() OVERRIDE { - ScopedFocusNotificationObserver root_observer(root_window()); - ScopedTargetFocusNotificationObserver observer1(root_window(), 1); - ScopedTargetFocusNotificationObserver observer2(root_window(), 2); - - root_observer.ExpectCounts(0, 0); - observer1.ExpectCounts(0, 0); - observer2.ExpectCounts(0, 0); - - FocusWindowById(1); - root_observer.ExpectCounts(1, 1); - observer1.ExpectCounts(1, 1); - observer2.ExpectCounts(0, 0); - - FocusWindowById(2); - root_observer.ExpectCounts(2, 2); - observer1.ExpectCounts(2, 2); - observer2.ExpectCounts(1, 1); - } - virtual void DuplicateFocusEvents() OVERRIDE { - // Focusing an existing focused window should not resend focus events. - ScopedFocusNotificationObserver root_observer(root_window()); - ScopedTargetFocusNotificationObserver observer1(root_window(), 1); - - root_observer.ExpectCounts(0, 0); - observer1.ExpectCounts(0, 0); - - FocusWindowById(1); - root_observer.ExpectCounts(1, 1); - observer1.ExpectCounts(1, 1); - - FocusWindowById(1); - root_observer.ExpectCounts(1, 1); - observer1.ExpectCounts(1, 1); - } - virtual void ActivationEvents() OVERRIDE { - ActivateWindowById(1); - - ScopedFocusNotificationObserver root_observer(root_window()); - ScopedTargetFocusNotificationObserver observer1(root_window(), 1); - ScopedTargetFocusNotificationObserver observer2(root_window(), 2); - - root_observer.ExpectCounts(0, 0); - observer1.ExpectCounts(0, 0); - observer2.ExpectCounts(0, 0); - - ActivateWindowById(2); - root_observer.ExpectCounts(1, 1); - observer1.ExpectCounts(1, 1); - observer2.ExpectCounts(1, 1); - } - virtual void ReactivationEvents() OVERRIDE { - ActivateWindowById(1); - ScopedFocusNotificationObserver root_observer(root_window()); - EXPECT_EQ(0, root_observer.reactivation_count()); - root_window()->GetChildById(2)->Hide(); - // When we attempt to activate "2", which cannot be activated because it - // is not visible, "1" will be reactivated. - ActivateWindowById(2); - EXPECT_EQ(1, root_observer.reactivation_count()); - EXPECT_EQ(root_window()->GetChildById(2), - root_observer.reactivation_requested_window()); - EXPECT_EQ(root_window()->GetChildById(1), - root_observer.reactivation_actual_window()); - } - virtual void DuplicateActivationEvents() OVERRIDE { - // Activating an existing active window should not resend activation events. - ActivateWindowById(1); - - ScopedFocusNotificationObserver root_observer(root_window()); - ScopedTargetFocusNotificationObserver observer1(root_window(), 1); - ScopedTargetFocusNotificationObserver observer2(root_window(), 2); - - root_observer.ExpectCounts(0, 0); - observer1.ExpectCounts(0, 0); - observer2.ExpectCounts(0, 0); - - ActivateWindowById(2); - root_observer.ExpectCounts(1, 1); - observer1.ExpectCounts(1, 1); - observer2.ExpectCounts(1, 1); - - ActivateWindowById(2); - root_observer.ExpectCounts(1, 1); - observer1.ExpectCounts(1, 1); - observer2.ExpectCounts(1, 1); - } - virtual void ShiftFocusWithinActiveWindow() OVERRIDE { - ActivateWindowById(1); - EXPECT_EQ(1, GetActiveWindowId()); - EXPECT_EQ(1, GetFocusedWindowId()); - FocusWindowById(11); - EXPECT_EQ(11, GetFocusedWindowId()); - FocusWindowById(12); - EXPECT_EQ(12, GetFocusedWindowId()); - } - virtual void ShiftFocusToChildOfInactiveWindow() OVERRIDE { - ActivateWindowById(2); - EXPECT_EQ(2, GetActiveWindowId()); - EXPECT_EQ(2, GetFocusedWindowId()); - FocusWindowById(11); - EXPECT_EQ(1, GetActiveWindowId()); - EXPECT_EQ(11, GetFocusedWindowId()); - } - virtual void ShiftFocusToParentOfFocusedWindow() OVERRIDE { - ActivateWindowById(1); - EXPECT_EQ(1, GetFocusedWindowId()); - FocusWindowById(11); - EXPECT_EQ(11, GetFocusedWindowId()); - FocusWindowById(1); - // Focus should _not_ shift to the parent of the already-focused window. - EXPECT_EQ(11, GetFocusedWindowId()); - } - virtual void FocusRulesOverride() OVERRIDE { - EXPECT_EQ(NULL, GetFocusedWindow()); - FocusWindowById(11); - EXPECT_EQ(11, GetFocusedWindowId()); - - test_focus_rules()->set_focus_restriction(root_window()->GetChildById(211)); - FocusWindowById(12); - // Input events leave focus unchanged; direct API calls will change focus - // to the restricted window. - int focused_window = IsInputEvent() ? 11 : 211; - EXPECT_EQ(focused_window, GetFocusedWindowId()); - - test_focus_rules()->set_focus_restriction(NULL); - FocusWindowById(12); - EXPECT_EQ(12, GetFocusedWindowId()); - } - virtual void ActivationRulesOverride() OVERRIDE { - ActivateWindowById(1); - EXPECT_EQ(1, GetActiveWindowId()); - EXPECT_EQ(1, GetFocusedWindowId()); - - aura::Window* w3 = root_window()->GetChildById(3); - test_focus_rules()->set_focus_restriction(w3); - - ActivateWindowById(2); - // Input events leave activation unchanged; direct API calls will activate - // the restricted window. - int active_window = IsInputEvent() ? 1 : 3; - EXPECT_EQ(active_window, GetActiveWindowId()); - EXPECT_EQ(active_window, GetFocusedWindowId()); - - test_focus_rules()->set_focus_restriction(NULL); - ActivateWindowById(2); - EXPECT_EQ(2, GetActiveWindowId()); - EXPECT_EQ(2, GetFocusedWindowId()); - } - virtual void ShiftFocusOnActivation() OVERRIDE { - // When a window is activated, by default that window is also focused. - // An ActivationChangeObserver may shift focus to another window within the - // same activatable window. - ActivateWindowById(2); - EXPECT_EQ(2, GetFocusedWindowId()); - ActivateWindowById(1); - EXPECT_EQ(1, GetFocusedWindowId()); - - ActivateWindowById(2); - - aura::Window* target = root_window()->GetChildById(1); - aura::client::ActivationClient* client = - aura::client::GetActivationClient(root_window()); - - scoped_ptr<FocusShiftingActivationObserver> observer( - new FocusShiftingActivationObserver(target)); - observer->set_shift_focus_to(target->GetChildById(11)); - client->AddObserver(observer.get()); - - ActivateWindowById(1); - - // w1's ActivationChangeObserver shifted focus to this child, pre-empting - // FocusController's default setting. - EXPECT_EQ(11, GetFocusedWindowId()); - - ActivateWindowById(2); - EXPECT_EQ(2, GetFocusedWindowId()); - - // Simulate a focus reset by the ActivationChangeObserver. This should - // trigger the default setting in FocusController. - observer->set_shift_focus_to(NULL); - ActivateWindowById(1); - EXPECT_EQ(1, GetFocusedWindowId()); - - client->RemoveObserver(observer.get()); - - ActivateWindowById(2); - EXPECT_EQ(2, GetFocusedWindowId()); - ActivateWindowById(1); - EXPECT_EQ(1, GetFocusedWindowId()); - } - virtual void ShiftFocusOnActivationDueToHide() OVERRIDE { - // Similar to ShiftFocusOnActivation except the activation change is - // triggered by hiding the active window. - ActivateWindowById(1); - EXPECT_EQ(1, GetFocusedWindowId()); - - // Removes window 3 as candidate for next activatable window. - root_window()->GetChildById(3)->Hide(); - EXPECT_EQ(1, GetFocusedWindowId()); - - aura::Window* target = root_window()->GetChildById(2); - aura::client::ActivationClient* client = - aura::client::GetActivationClient(root_window()); - - scoped_ptr<FocusShiftingActivationObserver> observer( - new FocusShiftingActivationObserver(target)); - observer->set_shift_focus_to(target->GetChildById(21)); - client->AddObserver(observer.get()); - - // Hide the active window. - root_window()->GetChildById(1)->Hide(); - - EXPECT_EQ(21, GetFocusedWindowId()); - - client->RemoveObserver(observer.get()); - } - virtual void NoShiftActiveOnActivation() OVERRIDE { - // When a window is activated, we need to prevent any change to activation - // from being made in response to an activation change notification. - } - - virtual void NoFocusChangeOnClickOnCaptureWindow() OVERRIDE { - scoped_ptr<aura::client::DefaultCaptureClient> capture_client( - new aura::client::DefaultCaptureClient(root_window())); - // Clicking on a window which has capture should not cause a focus change - // to the window. This test verifies whether that is indeed the case. - ActivateWindowById(1); - - EXPECT_EQ(1, GetActiveWindowId()); - EXPECT_EQ(1, GetFocusedWindowId()); - - aura::Window* w2 = root_window()->GetChildById(2); - aura::client::GetCaptureClient(root_window())->SetCapture(w2); - aura::test::EventGenerator generator(root_window(), w2); - generator.ClickLeftButton(); - - EXPECT_EQ(1, GetActiveWindowId()); - EXPECT_EQ(1, GetFocusedWindowId()); - aura::client::GetCaptureClient(root_window())->ReleaseCapture(w2); - } - - // Verifies focus change is honored while capture held. - virtual void ChangeFocusWhenNothingFocusedAndCaptured() OVERRIDE { - scoped_ptr<aura::client::DefaultCaptureClient> capture_client( - new aura::client::DefaultCaptureClient(root_window())); - aura::Window* w1 = root_window()->GetChildById(1); - aura::client::GetCaptureClient(root_window())->SetCapture(w1); - - EXPECT_EQ(-1, GetActiveWindowId()); - EXPECT_EQ(-1, GetFocusedWindowId()); - - FocusWindowById(1); - - EXPECT_EQ(1, GetActiveWindowId()); - EXPECT_EQ(1, GetFocusedWindowId()); - - aura::client::GetCaptureClient(root_window())->ReleaseCapture(w1); - } - - // Verfies if a window that loses activation is deleted during observer - // notification we don't pass the deleted window to other observers. - virtual void DontPassDeletedWindow() OVERRIDE { - FocusWindowById(1); - - EXPECT_EQ(1, GetActiveWindowId()); - EXPECT_EQ(1, GetFocusedWindowId()); - - DeleteOnLoseActivationChangeObserver observer1( - root_window()->GetChildById(1)); - RecordingActivationChangeObserver observer2(root_window()); - - FocusWindowById(2); - - EXPECT_EQ(2, GetActiveWindowId()); - EXPECT_EQ(2, GetFocusedWindowId()); - - EXPECT_TRUE(observer1.did_delete()); - ASSERT_EQ(1u, observer2.lost().size()); - EXPECT_TRUE(observer2.lost()[0] == NULL); - } - - private: - DISALLOW_COPY_AND_ASSIGN(FocusControllerDirectTestBase); -}; - -// Focus and Activation changes via aura::client::ActivationClient API. -class FocusControllerApiTest : public FocusControllerDirectTestBase { - public: - FocusControllerApiTest() {} - - private: - // Overridden from FocusControllerTestBase: - virtual void FocusWindowDirect(aura::Window* window) OVERRIDE { - FocusWindow(window); - } - virtual void ActivateWindowDirect(aura::Window* window) OVERRIDE { - ActivateWindow(window); - } - virtual void DeactivateWindowDirect(aura::Window* window) OVERRIDE { - DeactivateWindow(window); - } - virtual bool IsInputEvent() OVERRIDE { return false; } - - DISALLOW_COPY_AND_ASSIGN(FocusControllerApiTest); -}; - -// Focus and Activation changes via input events. -class FocusControllerMouseEventTest : public FocusControllerDirectTestBase { - public: - FocusControllerMouseEventTest() {} - - private: - // Overridden from FocusControllerTestBase: - virtual void FocusWindowDirect(aura::Window* window) OVERRIDE { - aura::test::EventGenerator generator(root_window(), window); - generator.ClickLeftButton(); - } - virtual void ActivateWindowDirect(aura::Window* window) OVERRIDE { - aura::test::EventGenerator generator(root_window(), window); - generator.ClickLeftButton(); - } - virtual void DeactivateWindowDirect(aura::Window* window) OVERRIDE { - aura::Window* next_activatable = - test_focus_rules()->GetNextActivatableWindow(window); - aura::test::EventGenerator generator(root_window(), next_activatable); - generator.ClickLeftButton(); - } - virtual bool IsInputEvent() OVERRIDE { return true; } - - DISALLOW_COPY_AND_ASSIGN(FocusControllerMouseEventTest); -}; - -class FocusControllerGestureEventTest : public FocusControllerDirectTestBase { - public: - FocusControllerGestureEventTest() {} - - private: - // Overridden from FocusControllerTestBase: - virtual void FocusWindowDirect(aura::Window* window) OVERRIDE { - aura::test::EventGenerator generator(root_window(), window); - generator.GestureTapAt(window->bounds().CenterPoint()); - } - virtual void ActivateWindowDirect(aura::Window* window) OVERRIDE { - aura::test::EventGenerator generator(root_window(), window); - generator.GestureTapAt(window->bounds().CenterPoint()); - } - virtual void DeactivateWindowDirect(aura::Window* window) OVERRIDE { - aura::Window* next_activatable = - test_focus_rules()->GetNextActivatableWindow(window); - aura::test::EventGenerator generator(root_window(), next_activatable); - generator.GestureTapAt(window->bounds().CenterPoint()); - } - virtual bool IsInputEvent() OVERRIDE { return true; } - - DISALLOW_COPY_AND_ASSIGN(FocusControllerGestureEventTest); -}; - -// Test base for tests where focus is implicitly set to a window as the result -// of a disposition change to the focused window or the hierarchy that contains -// it. -class FocusControllerImplicitTestBase : public FocusControllerTestBase { - protected: - explicit FocusControllerImplicitTestBase(bool parent) : parent_(parent) {} - - aura::Window* GetDispositionWindow(aura::Window* window) { - return parent_ ? window->parent() : window; - } - - // Change the disposition of |window| in such a way as it will lose focus. - virtual void ChangeWindowDisposition(aura::Window* window) = 0; - - // Allow each disposition change test to add additional post-disposition - // change expectations. - virtual void PostDispostionChangeExpectations() {} - - // Overridden from FocusControllerTestBase: - virtual void BasicFocus() OVERRIDE { - EXPECT_EQ(NULL, GetFocusedWindow()); - - aura::Window* w211 = root_window()->GetChildById(211); - FocusWindow(w211); - EXPECT_EQ(211, GetFocusedWindowId()); - - ChangeWindowDisposition(w211); - // BasicFocusRules passes focus to the parent. - EXPECT_EQ(parent_ ? 2 : 21, GetFocusedWindowId()); - } - virtual void BasicActivation() OVERRIDE { - DCHECK(!parent_) << "Activation tests don't support parent changes."; - - EXPECT_EQ(NULL, GetActiveWindow()); - - aura::Window* w2 = root_window()->GetChildById(2); - ActivateWindow(w2); - EXPECT_EQ(2, GetActiveWindowId()); - - ChangeWindowDisposition(w2); - EXPECT_EQ(3, GetActiveWindowId()); - PostDispostionChangeExpectations(); - } - virtual void FocusEvents() OVERRIDE { - aura::Window* w211 = root_window()->GetChildById(211); - FocusWindow(w211); - - ScopedFocusNotificationObserver root_observer(root_window()); - ScopedTargetFocusNotificationObserver observer211(root_window(), 211); - root_observer.ExpectCounts(0, 0); - observer211.ExpectCounts(0, 0); - - ChangeWindowDisposition(w211); - root_observer.ExpectCounts(0, 1); - observer211.ExpectCounts(0, 1); - } - virtual void ActivationEvents() OVERRIDE { - DCHECK(!parent_) << "Activation tests don't support parent changes."; - - aura::Window* w2 = root_window()->GetChildById(2); - ActivateWindow(w2); - - ScopedFocusNotificationObserver root_observer(root_window()); - ScopedTargetFocusNotificationObserver observer2(root_window(), 2); - ScopedTargetFocusNotificationObserver observer3(root_window(), 3); - root_observer.ExpectCounts(0, 0); - observer2.ExpectCounts(0, 0); - observer3.ExpectCounts(0, 0); - - ChangeWindowDisposition(w2); - root_observer.ExpectCounts(1, 1); - observer2.ExpectCounts(1, 1); - observer3.ExpectCounts(1, 1); - } - virtual void FocusRulesOverride() OVERRIDE { - EXPECT_EQ(NULL, GetFocusedWindow()); - aura::Window* w211 = root_window()->GetChildById(211); - FocusWindow(w211); - EXPECT_EQ(211, GetFocusedWindowId()); - - test_focus_rules()->set_focus_restriction(root_window()->GetChildById(11)); - ChangeWindowDisposition(w211); - // Normally, focus would shift to the parent (w21) but the override shifts - // it to 11. - EXPECT_EQ(11, GetFocusedWindowId()); - - test_focus_rules()->set_focus_restriction(NULL); - } - virtual void ActivationRulesOverride() OVERRIDE { - DCHECK(!parent_) << "Activation tests don't support parent changes."; - - aura::Window* w1 = root_window()->GetChildById(1); - ActivateWindow(w1); - - EXPECT_EQ(1, GetActiveWindowId()); - EXPECT_EQ(1, GetFocusedWindowId()); - - aura::Window* w3 = root_window()->GetChildById(3); - test_focus_rules()->set_focus_restriction(w3); - - // Normally, activation/focus would move to w2, but since we have a focus - // restriction, it should move to w3 instead. - ChangeWindowDisposition(w1); - EXPECT_EQ(3, GetActiveWindowId()); - EXPECT_EQ(3, GetFocusedWindowId()); - - test_focus_rules()->set_focus_restriction(NULL); - ActivateWindow(root_window()->GetChildById(2)); - EXPECT_EQ(2, GetActiveWindowId()); - EXPECT_EQ(2, GetFocusedWindowId()); - } - - private: - // When true, the disposition change occurs to the parent of the window - // instead of to the window. This verifies that changes occurring in the - // hierarchy that contains the window affect the window's focus. - bool parent_; - - DISALLOW_COPY_AND_ASSIGN(FocusControllerImplicitTestBase); -}; - -// Focus and Activation changes in response to window visibility changes. -class FocusControllerHideTest : public FocusControllerImplicitTestBase { - public: - FocusControllerHideTest() : FocusControllerImplicitTestBase(false) {} - - protected: - FocusControllerHideTest(bool parent) - : FocusControllerImplicitTestBase(parent) {} - - // Overridden from FocusControllerImplicitTestBase: - virtual void ChangeWindowDisposition(aura::Window* window) OVERRIDE { - GetDispositionWindow(window)->Hide(); - } - virtual void PostDispostionChangeExpectations() OVERRIDE { - // BasicActivation() starts with the stacking order: 1, 2, 3 (3 topmost) - // and then activates 2. After 2 is hidden in ChangeWindowDisposition - // above, 3 is activated, but code in - // FocusController::OnWindowVisibilityChanging keeps 2's layer above 3's - // until a hide animation completes (e.g. a fade-out transition). - aura::Window* w2 = root_window()->GetChildById(2); - aura::Window* w3 = root_window()->GetChildById(3); - - // W2 was hidden, but its layer should still be stacked above W3's. - typedef std::vector<ui::Layer*> Layers; - const Layers& children = w3->parent()->layer()->children(); - Layers::const_iterator w3_iter = - std::find(children.begin(), children.end(), w3->layer()); - Layers::const_iterator w2_iter = - std::find(children.begin(), children.end(), w2->layer()); - EXPECT_TRUE(w2_iter > w3_iter); - } - - private: - DISALLOW_COPY_AND_ASSIGN(FocusControllerHideTest); -}; - -// Focus and Activation changes in response to window parent visibility -// changes. -class FocusControllerParentHideTest : public FocusControllerHideTest { - public: - FocusControllerParentHideTest() : FocusControllerHideTest(true) {} - - private: - DISALLOW_COPY_AND_ASSIGN(FocusControllerParentHideTest); -}; - -// Focus and Activation changes in response to window destruction. -class FocusControllerDestructionTest : public FocusControllerImplicitTestBase { - public: - FocusControllerDestructionTest() : FocusControllerImplicitTestBase(false) {} - - protected: - FocusControllerDestructionTest(bool parent) - : FocusControllerImplicitTestBase(parent) {} - - // Overridden from FocusControllerImplicitTestBase: - virtual void ChangeWindowDisposition(aura::Window* window) OVERRIDE { - delete GetDispositionWindow(window); - } - - private: - DISALLOW_COPY_AND_ASSIGN(FocusControllerDestructionTest); -}; - -// Focus and Activation changes in response to window parent destruction. -class FocusControllerParentDestructionTest - : public FocusControllerDestructionTest { - public: - FocusControllerParentDestructionTest() - : FocusControllerDestructionTest(true) {} - - private: - DISALLOW_COPY_AND_ASSIGN(FocusControllerParentDestructionTest); -}; - -// Focus and Activation changes in response to window removal. -class FocusControllerRemovalTest : public FocusControllerImplicitTestBase { - public: - FocusControllerRemovalTest() : FocusControllerImplicitTestBase(false) {} - - protected: - FocusControllerRemovalTest(bool parent) - : FocusControllerImplicitTestBase(parent) {} - - // Overridden from FocusControllerImplicitTestBase: - virtual void ChangeWindowDisposition(aura::Window* window) OVERRIDE { - aura::Window* disposition_window = GetDispositionWindow(window); - disposition_window->parent()->RemoveChild(disposition_window); - window_owner_.reset(disposition_window); - } - virtual void TearDown() OVERRIDE { - window_owner_.reset(); - FocusControllerImplicitTestBase::TearDown(); - } - - private: - scoped_ptr<aura::Window> window_owner_; - - DISALLOW_COPY_AND_ASSIGN(FocusControllerRemovalTest); -}; - -// Focus and Activation changes in response to window parent removal. -class FocusControllerParentRemovalTest : public FocusControllerRemovalTest { - public: - FocusControllerParentRemovalTest() : FocusControllerRemovalTest(true) {} - - private: - DISALLOW_COPY_AND_ASSIGN(FocusControllerParentRemovalTest); -}; - - -#define FOCUS_CONTROLLER_TEST(TESTCLASS, TESTNAME) \ - TEST_F(TESTCLASS, TESTNAME) { TESTNAME(); } - -// Runs direct focus change tests (input events and API calls). -#define DIRECT_FOCUS_CHANGE_TESTS(TESTNAME) \ - FOCUS_CONTROLLER_TEST(FocusControllerApiTest, TESTNAME) \ - FOCUS_CONTROLLER_TEST(FocusControllerMouseEventTest, TESTNAME) \ - FOCUS_CONTROLLER_TEST(FocusControllerGestureEventTest, TESTNAME) - -// Runs implicit focus change tests for disposition changes to target. -#define IMPLICIT_FOCUS_CHANGE_TARGET_TESTS(TESTNAME) \ - FOCUS_CONTROLLER_TEST(FocusControllerHideTest, TESTNAME) \ - FOCUS_CONTROLLER_TEST(FocusControllerDestructionTest, TESTNAME) \ - FOCUS_CONTROLLER_TEST(FocusControllerRemovalTest, TESTNAME) - -// Runs implicit focus change tests for disposition changes to target's parent -// hierarchy. -#define IMPLICIT_FOCUS_CHANGE_PARENT_TESTS(TESTNAME) \ - /* TODO(beng): parent destruction tests are not supported at - present due to workspace manager issues. \ - FOCUS_CONTROLLER_TEST(FocusControllerParentDestructionTest, TESTNAME) */ \ - FOCUS_CONTROLLER_TEST(FocusControllerParentHideTest, TESTNAME) \ - FOCUS_CONTROLLER_TEST(FocusControllerParentRemovalTest, TESTNAME) - -// Runs all implicit focus change tests (changes to the target and target's -// parent hierarchy) -#define IMPLICIT_FOCUS_CHANGE_TESTS(TESTNAME) \ - IMPLICIT_FOCUS_CHANGE_TARGET_TESTS(TESTNAME) \ - IMPLICIT_FOCUS_CHANGE_PARENT_TESTS(TESTNAME) - -// Runs all possible focus change tests. -#define ALL_FOCUS_TESTS(TESTNAME) \ - DIRECT_FOCUS_CHANGE_TESTS(TESTNAME) \ - IMPLICIT_FOCUS_CHANGE_TESTS(TESTNAME) - -// Runs focus change tests that apply only to the target. For example, -// implicit activation changes caused by window disposition changes do not -// occur when changes to the containing hierarchy happen. -#define TARGET_FOCUS_TESTS(TESTNAME) \ - DIRECT_FOCUS_CHANGE_TESTS(TESTNAME) \ - IMPLICIT_FOCUS_CHANGE_TARGET_TESTS(TESTNAME) - -// - Focuses a window, verifies that focus changed. -ALL_FOCUS_TESTS(BasicFocus); - -// - Activates a window, verifies that activation changed. -TARGET_FOCUS_TESTS(BasicActivation); - -// - Focuses a window, verifies that focus events were dispatched. -ALL_FOCUS_TESTS(FocusEvents); - -// - Focuses or activates a window multiple times, verifies that events are only -// dispatched when focus/activation actually changes. -DIRECT_FOCUS_CHANGE_TESTS(DuplicateFocusEvents); -DIRECT_FOCUS_CHANGE_TESTS(DuplicateActivationEvents); - -// - Activates a window, verifies that activation events were dispatched. -TARGET_FOCUS_TESTS(ActivationEvents); - -// - Attempts to active a hidden window, verifies that current window is -// attempted to be reactivated and the appropriate event dispatched. -FOCUS_CONTROLLER_TEST(FocusControllerApiTest, ReactivationEvents); - -// - Input events/API calls shift focus between focusable windows within the -// active window. -DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusWithinActiveWindow); - -// - Input events/API calls to a child window of an inactive window shifts -// activation to the activatable parent and focuses the child. -DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusToChildOfInactiveWindow); - -// - Input events/API calls to focus the parent of the focused window do not -// shift focus away from the child. -DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusToParentOfFocusedWindow); - -// - Verifies that FocusRules determine what can be focused. -ALL_FOCUS_TESTS(FocusRulesOverride); - -// - Verifies that FocusRules determine what can be activated. -TARGET_FOCUS_TESTS(ActivationRulesOverride); - -// - Verifies that attempts to change focus or activation from a focus or -// activation change observer are ignored. -DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusOnActivation); -DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusOnActivationDueToHide); -DIRECT_FOCUS_CHANGE_TESTS(NoShiftActiveOnActivation); - -// Clicking on a window which has capture should not result in a focus change. -DIRECT_FOCUS_CHANGE_TESTS(NoFocusChangeOnClickOnCaptureWindow); - -FOCUS_CONTROLLER_TEST(FocusControllerApiTest, - ChangeFocusWhenNothingFocusedAndCaptured); - -// See description above DontPassDeletedWindow() for details. -FOCUS_CONTROLLER_TEST(FocusControllerApiTest, DontPassDeletedWindow); - -} // namespace corewm -} // namespace views diff --git a/chromium/ui/views/corewm/focus_rules.h b/chromium/ui/views/corewm/focus_rules.h deleted file mode 100644 index 559a2385432..00000000000 --- a/chromium/ui/views/corewm/focus_rules.h +++ /dev/null @@ -1,68 +0,0 @@ -// 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. - -#ifndef UI_VIEWS_COREWM_FOCUS_RULES_H_ -#define UI_VIEWS_COREWM_FOCUS_RULES_H_ - -#include "ui/views/views_export.h" - -namespace aura { -class Window; -} - -namespace views { -namespace corewm { - -// Implemented by an object that establishes the rules about what can be -// focused or activated. -class VIEWS_EXPORT FocusRules { - public: - virtual ~FocusRules() {} - - // Returns true if |window| is a toplevel window. Whether or not a window - // is considered toplevel is determined by a similar set of rules that - // govern activation and focus. Not all toplevel windows are activatable, - // call CanActivateWindow() to determine if a window can be activated. - virtual bool IsToplevelWindow(aura::Window* window) const = 0; - // Returns true if |window| can be activated or focused. - virtual bool CanActivateWindow(aura::Window* window) const = 0; - // For CanFocusWindow(), NULL is supported, because NULL is a valid focusable - // window (in the case of clearing focus). - virtual bool CanFocusWindow(aura::Window* window) const = 0; - - // Returns the toplevel window containing |window|. Not all toplevel windows - // are activatable, call GetActivatableWindow() instead to return the - // activatable window, which might be in a different hierarchy. - // Will return NULL if |window| is not contained by a window considered to be - // a toplevel window. - virtual aura::Window* GetToplevelWindow(aura::Window* window) const = 0; - // Returns the activatable or focusable window given an attempt to activate or - // focus |window|. Some possible scenarios (not intended to be exhaustive): - // - |window| is a child of a non-focusable window and so focus must be set - // according to rules defined by the delegate, e.g. to a parent. - // - |window| is an activatable window that is the transient parent of a modal - // window, so attempts to activate |window| should result in the modal - // transient being activated instead. - // These methods may return NULL if they are unable to find an activatable - // or focusable window given |window|. - virtual aura::Window* GetActivatableWindow(aura::Window* window) const = 0; - virtual aura::Window* GetFocusableWindow(aura::Window* window) const = 0; - - // Returns the next window to activate in the event that |ignore| is no longer - // activatable. This function is called when something is happening to - // |ignore| that means it can no longer have focus or activation, including - // but not limited to: - // - it or its parent hierarchy is being hidden, or removed from the - // RootWindow. - // - it is being destroyed. - // - it is being explicitly deactivated. - // |ignore| cannot be NULL. - virtual aura::Window* GetNextActivatableWindow( - aura::Window* ignore) const = 0; -}; - -} // namespace corewm -} // namespace views - -#endif // UI_VIEWS_COREWM_FOCUS_RULES_H_ diff --git a/chromium/ui/views/corewm/image_grid.cc b/chromium/ui/views/corewm/image_grid.cc deleted file mode 100644 index 29c775773c7..00000000000 --- a/chromium/ui/views/corewm/image_grid.cc +++ /dev/null @@ -1,308 +0,0 @@ -// 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. - -#include "ui/views/corewm/image_grid.h" - -#include <algorithm> - -#include "third_party/skia/include/core/SkColor.h" -#include "third_party/skia/include/core/SkXfermode.h" -#include "ui/compositor/dip_util.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/image/image.h" -#include "ui/gfx/rect.h" -#include "ui/gfx/rect_conversions.h" -#include "ui/gfx/size.h" -#include "ui/gfx/size_conversions.h" -#include "ui/gfx/transform.h" - -using std::max; -using std::min; - -namespace views { -namespace corewm { - -gfx::RectF ImageGrid::TestAPI::GetTransformedLayerBounds( - const ui::Layer& layer) { - gfx::RectF bounds = layer.bounds(); - layer.transform().TransformRect(&bounds); - return bounds; -} - -ImageGrid::ImageGrid() - : layer_(new ui::Layer(ui::LAYER_NOT_DRAWN)), - top_image_height_(0), - bottom_image_height_(0), - left_image_width_(0), - right_image_width_(0), - base_top_row_height_(0), - base_bottom_row_height_(0), - base_left_column_width_(0), - base_right_column_width_(0) { -} - -ImageGrid::~ImageGrid() { -} - -void ImageGrid::SetImages(const gfx::Image* top_left_image, - const gfx::Image* top_image, - const gfx::Image* top_right_image, - const gfx::Image* left_image, - const gfx::Image* center_image, - const gfx::Image* right_image, - const gfx::Image* bottom_left_image, - const gfx::Image* bottom_image, - const gfx::Image* bottom_right_image) { - SetImage(top_left_image, &top_left_layer_, &top_left_painter_); - SetImage(top_image, &top_layer_, &top_painter_); - SetImage(top_right_image, &top_right_layer_, &top_right_painter_); - SetImage(left_image, &left_layer_, &left_painter_); - SetImage(center_image, ¢er_layer_, ¢er_painter_); - SetImage(right_image, &right_layer_, &right_painter_); - SetImage(bottom_left_image, &bottom_left_layer_, &bottom_left_painter_); - SetImage(bottom_image, &bottom_layer_, &bottom_painter_); - SetImage(bottom_right_image, &bottom_right_layer_, &bottom_right_painter_); - - top_image_height_ = GetImageSize(top_image).height(); - bottom_image_height_ = GetImageSize(bottom_image).height(); - left_image_width_ = GetImageSize(left_image).width(); - right_image_width_ = GetImageSize(right_image).width(); - - base_top_row_height_ = max(GetImageSize(top_left_image).height(), - max(GetImageSize(top_image).height(), - GetImageSize(top_right_image).height())); - base_bottom_row_height_ = max(GetImageSize(bottom_left_image).height(), - max(GetImageSize(bottom_image).height(), - GetImageSize(bottom_right_image).height())); - base_left_column_width_ = max(GetImageSize(top_left_image).width(), - max(GetImageSize(left_image).width(), - GetImageSize(bottom_left_image).width())); - base_right_column_width_ = max(GetImageSize(top_right_image).width(), - max(GetImageSize(right_image).width(), - GetImageSize(bottom_right_image).width())); - - // Invalidate previous |size_| so calls to SetSize() will recompute it. - size_.SetSize(0, 0); -} - -void ImageGrid::SetSize(const gfx::Size& size) { - if (size_ == size) - return; - - size_ = size; - - gfx::Rect updated_bounds = layer_->bounds(); - updated_bounds.set_size(size); - layer_->SetBounds(updated_bounds); - - // Calculate the available amount of space for corner images on all sides of - // the grid. If the images don't fit, we need to clip them. - const int left = min(base_left_column_width_, size_.width() / 2); - const int right = min(base_right_column_width_, size_.width() - left); - const int top = min(base_top_row_height_, size_.height() / 2); - const int bottom = min(base_bottom_row_height_, size_.height() - top); - - // The remaining space goes to the center image. - int center_width = std::max(size.width() - left - right, 0); - int center_height = std::max(size.height() - top - bottom, 0); - - // At non-integer scale factors, the ratio of dimensions in DIP is not - // necessarily the same as the ratio in physical pixels due to rounding. Set - // the transform on each of the layers based on dimensions in pixels. - gfx::Size center_size_in_pixels = gfx::ToFlooredSize(gfx::ScaleSize( - gfx::Size(center_width, center_height), layer_->device_scale_factor())); - - if (top_layer_.get()) { - if (center_width > 0) { - gfx::Transform transform; - transform.Translate(left, 0); - ScaleWidth(center_size_in_pixels, top_layer_.get(), transform); - top_layer_->SetTransform(transform); - } - top_layer_->SetVisible(center_width > 0); - } - if (bottom_layer_.get()) { - if (center_width > 0) { - gfx::Transform transform; - transform.Translate( - left, size.height() - bottom_layer_->bounds().height()); - ScaleWidth(center_size_in_pixels, bottom_layer_.get(), transform); - bottom_layer_->SetTransform(transform); - } - bottom_layer_->SetVisible(center_width > 0); - } - if (left_layer_.get()) { - if (center_height > 0) { - gfx::Transform transform; - transform.Translate(0, top); - ScaleHeight(center_size_in_pixels, left_layer_.get(), transform); - left_layer_->SetTransform(transform); - } - left_layer_->SetVisible(center_height > 0); - } - if (right_layer_.get()) { - if (center_height > 0) { - gfx::Transform transform; - transform.Translate( - size.width() - right_layer_->bounds().width(), top); - ScaleHeight(center_size_in_pixels, right_layer_.get(), transform); - right_layer_->SetTransform(transform); - } - right_layer_->SetVisible(center_height > 0); - } - - if (top_left_layer_.get()) { - // No transformation needed; it should be at (0, 0) and unscaled. - top_left_painter_->SetClipRect( - LayerExceedsSize(top_left_layer_.get(), gfx::Size(left, top)) ? - gfx::Rect(gfx::Rect(0, 0, left, top)) : - gfx::Rect(), - top_left_layer_.get()); - } - if (top_right_layer_.get()) { - gfx::Transform transform; - transform.Translate(size.width() - top_right_layer_->bounds().width(), 0.0); - top_right_layer_->SetTransform(transform); - top_right_painter_->SetClipRect( - LayerExceedsSize(top_right_layer_.get(), gfx::Size(right, top)) ? - gfx::Rect(top_right_layer_->bounds().width() - right, 0, - right, top) : - gfx::Rect(), - top_right_layer_.get()); - } - if (bottom_left_layer_.get()) { - gfx::Transform transform; - transform.Translate( - 0.0, size.height() - bottom_left_layer_->bounds().height()); - bottom_left_layer_->SetTransform(transform); - bottom_left_painter_->SetClipRect( - LayerExceedsSize(bottom_left_layer_.get(), gfx::Size(left, bottom)) ? - gfx::Rect(0, bottom_left_layer_->bounds().height() - bottom, - left, bottom) : - gfx::Rect(), - bottom_left_layer_.get()); - } - if (bottom_right_layer_.get()) { - gfx::Transform transform; - transform.Translate( - size.width() - bottom_right_layer_->bounds().width(), - size.height() - bottom_right_layer_->bounds().height()); - bottom_right_layer_->SetTransform(transform); - bottom_right_painter_->SetClipRect( - LayerExceedsSize(bottom_right_layer_.get(), gfx::Size(right, bottom)) ? - gfx::Rect(bottom_right_layer_->bounds().width() - right, - bottom_right_layer_->bounds().height() - bottom, - right, bottom) : - gfx::Rect(), - bottom_right_layer_.get()); - } - - if (center_layer_.get()) { - if (center_width > 0 && center_height > 0) { - gfx::Transform transform; - transform.Translate(left, top); - transform.Scale(center_width / center_layer_->bounds().width(), - center_height / center_layer_->bounds().height()); - center_layer_->SetTransform(transform); - } - center_layer_->SetVisible(center_width > 0 && center_height > 0); - } -} - -void ImageGrid::SetContentBounds(const gfx::Rect& content_bounds) { - - SetSize(gfx::Size( - content_bounds.width() + left_image_width_ + right_image_width_, - content_bounds.height() + top_image_height_ + - bottom_image_height_)); - layer_->SetBounds( - gfx::Rect(content_bounds.x() - left_image_width_, - content_bounds.y() - top_image_height_, - layer_->bounds().width(), - layer_->bounds().height())); -} - -void ImageGrid::ImagePainter::SetClipRect(const gfx::Rect& clip_rect, - ui::Layer* layer) { - if (clip_rect != clip_rect_) { - clip_rect_ = clip_rect; - layer->SchedulePaint(layer->bounds()); - } -} - -void ImageGrid::ImagePainter::OnPaintLayer(gfx::Canvas* canvas) { - if (!clip_rect_.IsEmpty()) - canvas->ClipRect(clip_rect_); - canvas->DrawImageInt(*(image_->ToImageSkia()), 0, 0); -} - -void ImageGrid::ImagePainter::OnDeviceScaleFactorChanged( - float device_scale_factor) { - // Redrawing will take care of scale factor change. -} - -base::Closure ImageGrid::ImagePainter::PrepareForLayerBoundsChange() { - return base::Closure(); -} - -// static -gfx::Size ImageGrid::GetImageSize(const gfx::Image* image) { - return image ? - gfx::Size(image->ToImageSkia()->width(), image->ToImageSkia()->height()) : - gfx::Size(); -} - -// static -bool ImageGrid::LayerExceedsSize(const ui::Layer* layer, - const gfx::Size& size) { - return layer->bounds().width() > size.width() || - layer->bounds().height() > size.height(); -} - -void ImageGrid::SetImage(const gfx::Image* image, - scoped_ptr<ui::Layer>* layer_ptr, - scoped_ptr<ImagePainter>* painter_ptr) { - // Clean out old layers and painters. - if (layer_ptr->get()) - layer_->Remove(layer_ptr->get()); - layer_ptr->reset(); - painter_ptr->reset(); - - // If we're not using an image, we're done. - if (!image) - return; - - // Set up the new layer and painter. - layer_ptr->reset(new ui::Layer(ui::LAYER_TEXTURED)); - - const gfx::Size size = GetImageSize(image); - layer_ptr->get()->SetBounds(gfx::Rect(0, 0, size.width(), size.height())); - - painter_ptr->reset(new ImagePainter(image)); - layer_ptr->get()->set_delegate(painter_ptr->get()); - layer_ptr->get()->SetFillsBoundsOpaquely(false); - layer_ptr->get()->SetVisible(true); - layer_->Add(layer_ptr->get()); -} - -void ImageGrid::ScaleWidth(gfx::Size center, - ui::Layer* layer, - gfx::Transform& transform) { - int layer_width = ConvertSizeToPixel(layer, - layer->bounds().size()).width(); - float scale = static_cast<float>(center.width()) / layer_width; - transform.Scale(scale, 1.0); -} - -void ImageGrid::ScaleHeight(gfx::Size center, - ui::Layer* layer, - gfx::Transform& transform) { - int layer_height = ConvertSizeToPixel(layer, - layer->bounds().size()).height(); - float scale = static_cast<float>(center.height()) / layer_height; - transform.Scale(1.0, scale); -} - -} // namespace corewm -} // namespace views diff --git a/chromium/ui/views/corewm/image_grid.h b/chromium/ui/views/corewm/image_grid.h deleted file mode 100644 index 51b1b56ee62..00000000000 --- a/chromium/ui/views/corewm/image_grid.h +++ /dev/null @@ -1,228 +0,0 @@ -// 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. - -#ifndef UI_VIEWS_COREWM_IMAGE_GRID_H_ -#define UI_VIEWS_COREWM_IMAGE_GRID_H_ - -#include "base/basictypes.h" -#include "base/gtest_prod_util.h" -#include "base/memory/scoped_ptr.h" -#include "ui/compositor/layer.h" -#include "ui/compositor/layer_delegate.h" -#include "ui/gfx/rect.h" -#include "ui/gfx/size.h" -#include "ui/views/views_export.h" - -namespace gfx { -class Image; -} // namespace gfx - -namespace views { -namespace corewm { - -// An ImageGrid is a 3x3 array of ui::Layers, each containing an image. -// -// As the grid is resized, its images fill the requested space: -// - corner images are not scaled -// - top and bottom images are scaled horizontally -// - left and right images are scaled vertically -// - the center image is scaled in both directions -// -// If one of the non-center images is smaller than the largest images in its -// row or column, it will be aligned with the outside of the grid. For -// example, given 4x4 top-left and top-right images and a 1x2 top images: -// -// +--------+---------------------+--------+ -// | | top | | -// | top- +---------------------+ top- + -// | left | | right | -// +----+---+ +---+----+ -// | | | | -// ... -// -// This may seem odd at first, but it lets ImageGrid be used to draw shadows -// with curved corners that extend inwards beyond a window's borders. In the -// below example, the top-left corner image is overlaid on top of the window's -// top-left corner: -// -// +---------+----------------------- -// | ..xxx|XXXXXXXXXXXXXXXXXX -// | .xXXXXX|XXXXXXXXXXXXXXXXXX_____ -// | .xXX | ^ window's top edge -// | .xXX | -// +---------+ -// | xXX| -// | xXX|< window's left edge -// | xXX| -// ... -// -class VIEWS_EXPORT ImageGrid { - public: - // Helper class for use by tests. - class VIEWS_EXPORT TestAPI { - public: - TestAPI(ImageGrid* grid) : grid_(grid) {} - - gfx::Rect top_left_clip_rect() const { - return grid_->top_left_painter_->clip_rect_; - } - gfx::Rect top_right_clip_rect() const { - return grid_->top_right_painter_->clip_rect_; - } - gfx::Rect bottom_left_clip_rect() const { - return grid_->bottom_left_painter_->clip_rect_; - } - gfx::Rect bottom_right_clip_rect() const { - return grid_->bottom_right_painter_->clip_rect_; - } - - // Returns |layer|'s bounds after applying the layer's current transform. - gfx::RectF GetTransformedLayerBounds(const ui::Layer& layer); - - private: - ImageGrid* grid_; // not owned - - DISALLOW_COPY_AND_ASSIGN(TestAPI); - }; - - ImageGrid(); - ~ImageGrid(); - - ui::Layer* layer() { return layer_.get(); } - int top_image_height() const { return top_image_height_; } - int bottom_image_height() const { return bottom_image_height_; } - int left_image_width() const { return left_image_width_; } - int right_image_width() const { return right_image_width_; } - - // Visible to allow independent layer animations and for testing. - ui::Layer* top_left_layer() const { return top_left_layer_.get(); } - ui::Layer* top_layer() const { return top_layer_.get(); } - ui::Layer* top_right_layer() const { return top_right_layer_.get(); } - ui::Layer* left_layer() const { return left_layer_.get(); } - ui::Layer* center_layer() const { return center_layer_.get(); } - ui::Layer* right_layer() const { return right_layer_.get(); } - ui::Layer* bottom_left_layer() const { return bottom_left_layer_.get(); } - ui::Layer* bottom_layer() const { return bottom_layer_.get(); } - ui::Layer* bottom_right_layer() const { return bottom_right_layer_.get(); } - - // Sets the grid to display the passed-in images (any of which can be NULL). - // Ownership of the images remains with the caller. May be called more than - // once to switch images. - void SetImages(const gfx::Image* top_left_image, - const gfx::Image* top_image, - const gfx::Image* top_right_image, - const gfx::Image* left_image, - const gfx::Image* center_image, - const gfx::Image* right_image, - const gfx::Image* bottom_left_image, - const gfx::Image* bottom_image, - const gfx::Image* bottom_right_image); - - void SetSize(const gfx::Size& size); - - // Sets the grid to a position and size such that the inner edges of the top, - // bottom, left and right images will be flush with |content_bounds_in_dip|. - void SetContentBounds(const gfx::Rect& content_bounds_in_dip); - - private: - // Delegate responsible for painting a specific image on a layer. - class ImagePainter : public ui::LayerDelegate { - public: - ImagePainter(const gfx::Image* image) : image_(image) {} - virtual ~ImagePainter() {} - - // Clips |layer| to |clip_rect|. Triggers a repaint if the clipping - // rectangle has changed. An empty rectangle disables clipping. - void SetClipRect(const gfx::Rect& clip_rect, ui::Layer* layer); - - // ui::LayerDelegate implementation: - virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE; - virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE; - virtual base::Closure PrepareForLayerBoundsChange() OVERRIDE; - - private: - friend class TestAPI; - - const gfx::Image* image_; // not owned - - gfx::Rect clip_rect_; - - DISALLOW_COPY_AND_ASSIGN(ImagePainter); - }; - - // Returns the dimensions of |image| if non-NULL or gfx::Size(0, 0) otherwise. - static gfx::Size GetImageSize(const gfx::Image* image); - - // Returns true if |layer|'s bounds don't fit within |size|. - static bool LayerExceedsSize(const ui::Layer* layer, const gfx::Size& size); - - // Sets |layer_ptr| and |painter_ptr| to display |image| and adds the - // passed-in layer to |layer_|. If image is NULL resets |layer_ptr| and - // |painter_ptr| and removes any existing layer from |layer_|. - void SetImage(const gfx::Image* image, - scoped_ptr<ui::Layer>* layer_ptr, - scoped_ptr<ImagePainter>* painter_ptr); - - // Sets the scaling for the transform applied to a layer. The left, top, - // right and bottom layers are stretched to the height or width of the - // center image. - void ScaleWidth(gfx::Size center, - ui::Layer* layer, - gfx::Transform& transform); - void ScaleHeight(gfx::Size center, - ui::Layer* layer, - gfx::Transform& transform); - - // Layer that contains all of the image layers. - scoped_ptr<ui::Layer> layer_; - - // The grid's dimensions. - gfx::Size size_; - - // Heights and widths of the images displayed by |top_layer_|, - // |bottom_layer_|, |left_layer_|, and |right_layer_|. - int top_image_height_; - int bottom_image_height_; - int left_image_width_; - int right_image_width_; - - // Heights of the tallest images in the top and bottom rows and the widest - // images in the left and right columns. Note that we may have less actual - // space than this available if the images are large and |size_| is small. - int base_top_row_height_; - int base_bottom_row_height_; - int base_left_column_width_; - int base_right_column_width_; - - // Layers used to display the various images. Children of |layer_|. - // Positions for which no images were supplied are NULL. - scoped_ptr<ui::Layer> top_left_layer_; - scoped_ptr<ui::Layer> top_layer_; - scoped_ptr<ui::Layer> top_right_layer_; - scoped_ptr<ui::Layer> left_layer_; - scoped_ptr<ui::Layer> center_layer_; - scoped_ptr<ui::Layer> right_layer_; - scoped_ptr<ui::Layer> bottom_left_layer_; - scoped_ptr<ui::Layer> bottom_layer_; - scoped_ptr<ui::Layer> bottom_right_layer_; - - // Delegates responsible for painting the above layers. - // Positions for which no images were supplied are NULL. - scoped_ptr<ImagePainter> top_left_painter_; - scoped_ptr<ImagePainter> top_painter_; - scoped_ptr<ImagePainter> top_right_painter_; - scoped_ptr<ImagePainter> left_painter_; - scoped_ptr<ImagePainter> center_painter_; - scoped_ptr<ImagePainter> right_painter_; - scoped_ptr<ImagePainter> bottom_left_painter_; - scoped_ptr<ImagePainter> bottom_painter_; - scoped_ptr<ImagePainter> bottom_right_painter_; - - DISALLOW_COPY_AND_ASSIGN(ImageGrid); -}; - -} // namespace corewm -} // namespace views - -#endif // UI_VIEWS_COREWM_IMAGE_GRID_H_ diff --git a/chromium/ui/views/corewm/image_grid_unittest.cc b/chromium/ui/views/corewm/image_grid_unittest.cc deleted file mode 100644 index 4b5508d733d..00000000000 --- a/chromium/ui/views/corewm/image_grid_unittest.cc +++ /dev/null @@ -1,341 +0,0 @@ -// 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. - -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/skia/include/core/SkBitmap.h" -#include "ui/views/test/views_test_base.h" -#include "ui/gfx/image/image.h" -#include "ui/gfx/image/image_skia.h" -#include "ui/views/corewm/image_grid.h" - -namespace views { -namespace corewm { - -namespace { - -// Creates a gfx::Image with the requested dimensions. -gfx::Image* CreateImage(const gfx::Size& size) { - SkBitmap bitmap; - bitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height()); - return new gfx::Image(gfx::ImageSkia::CreateFrom1xBitmap(bitmap)); -} - -} // namespace - -typedef ViewsTestBase ImageGridTest; - -// Test that an ImageGrid's layers are transformed correctly when SetSize() is -// called. -TEST_F(ImageGridTest, Basic) { - // Size of the images around the grid's border. - const int kBorder = 2; - - scoped_ptr<gfx::Image> image_1x1(CreateImage(gfx::Size(1, 1))); - scoped_ptr<gfx::Image> image_1xB(CreateImage(gfx::Size(1, kBorder))); - scoped_ptr<gfx::Image> image_Bx1(CreateImage(gfx::Size(kBorder, 1))); - scoped_ptr<gfx::Image> image_BxB(CreateImage(gfx::Size(kBorder, kBorder))); - - ImageGrid grid; - grid.SetImages(image_BxB.get(), image_1xB.get(), image_BxB.get(), - image_Bx1.get(), image_1x1.get(), image_Bx1.get(), - image_BxB.get(), image_1xB.get(), image_BxB.get()); - - ImageGrid::TestAPI test_api(&grid); - ASSERT_TRUE(grid.top_left_layer() != NULL); - ASSERT_TRUE(grid.top_layer() != NULL); - ASSERT_TRUE(grid.top_right_layer() != NULL); - ASSERT_TRUE(grid.left_layer() != NULL); - ASSERT_TRUE(grid.center_layer() != NULL); - ASSERT_TRUE(grid.right_layer() != NULL); - ASSERT_TRUE(grid.bottom_left_layer() != NULL); - ASSERT_TRUE(grid.bottom_layer() != NULL); - ASSERT_TRUE(grid.bottom_right_layer() != NULL); - - const gfx::Size size(20, 30); - grid.SetSize(size); - - // The top-left layer should be flush with the top-left corner and unscaled. - EXPECT_EQ(gfx::RectF(0, 0, kBorder, kBorder).ToString(), - test_api.GetTransformedLayerBounds( - *grid.top_left_layer()).ToString()); - - // The top layer should be flush with the top edge and stretched horizontally - // between the two top corners. - EXPECT_EQ(gfx::RectF( - kBorder, 0, size.width() - 2 * kBorder, kBorder).ToString(), - test_api.GetTransformedLayerBounds( - *grid.top_layer()).ToString()); - - // The top-right layer should be flush with the top-right corner and unscaled. - EXPECT_EQ(gfx::RectF(size.width() - kBorder, 0, kBorder, kBorder).ToString(), - test_api.GetTransformedLayerBounds( - *grid.top_right_layer()).ToString()); - - // The left layer should be flush with the left edge and stretched vertically - // between the two left corners. - EXPECT_EQ(gfx::RectF( - 0, kBorder, kBorder, size.height() - 2 * kBorder).ToString(), - test_api.GetTransformedLayerBounds( - *grid.left_layer()).ToString()); - - // The center layer should fill the space in the middle of the grid. - EXPECT_EQ(gfx::RectF( - kBorder, kBorder, size.width() - 2 * kBorder, - size.height() - 2 * kBorder).ToString(), - test_api.GetTransformedLayerBounds( - *grid.center_layer()).ToString()); - - // The right layer should be flush with the right edge and stretched - // vertically between the two right corners. - EXPECT_EQ(gfx::RectF( - size.width() - kBorder, kBorder, - kBorder, size.height() - 2 * kBorder).ToString(), - test_api.GetTransformedLayerBounds( - *grid.right_layer()).ToString()); - - // The bottom-left layer should be flush with the bottom-left corner and - // unscaled. - EXPECT_EQ(gfx::RectF(0, size.height() - kBorder, kBorder, kBorder).ToString(), - test_api.GetTransformedLayerBounds( - *grid.bottom_left_layer()).ToString()); - - // The bottom layer should be flush with the bottom edge and stretched - // horizontally between the two bottom corners. - EXPECT_EQ(gfx::RectF( - kBorder, size.height() - kBorder, - size.width() - 2 * kBorder, kBorder).ToString(), - test_api.GetTransformedLayerBounds( - *grid.bottom_layer()).ToString()); - - // The bottom-right layer should be flush with the bottom-right corner and - // unscaled. - EXPECT_EQ(gfx::RectF( - size.width() - kBorder, size.height() - kBorder, - kBorder, kBorder).ToString(), - test_api.GetTransformedLayerBounds( - *grid.bottom_right_layer()).ToString()); -} - -// Test that an ImageGrid's layers are transformed correctly when -// SetContentBounds() is called. -TEST_F(ImageGridTest, SetContentBounds) { - // Size of the images around the grid's border. - const int kBorder = 2; - - scoped_ptr<gfx::Image> image_1x1(CreateImage(gfx::Size(1, 1))); - scoped_ptr<gfx::Image> image_1xB(CreateImage(gfx::Size(1, kBorder))); - scoped_ptr<gfx::Image> image_Bx1(CreateImage(gfx::Size(kBorder, 1))); - scoped_ptr<gfx::Image> image_BxB(CreateImage(gfx::Size(kBorder, kBorder))); - - ImageGrid grid; - grid.SetImages(image_BxB.get(), image_1xB.get(), image_BxB.get(), - image_Bx1.get(), image_1x1.get(), image_Bx1.get(), - image_BxB.get(), image_1xB.get(), image_BxB.get()); - - ImageGrid::TestAPI test_api(&grid); - - const gfx::Point origin(5, 10); - const gfx::Size size(20, 30); - grid.SetContentBounds(gfx::Rect(origin, size)); - - // The master layer is positioned above the top-left corner of the content - // bounds and has height/width that contain the grid and bounds. - EXPECT_EQ(gfx::RectF(origin.x() - kBorder, - origin.y() - kBorder, - size.width() + 2 * kBorder, - size.height() + 2 * kBorder).ToString(), - test_api.GetTransformedLayerBounds(*grid.layer()).ToString()); -} - -// Check that we don't crash if only a single image is supplied. -TEST_F(ImageGridTest, SingleImage) { - const int kBorder = 1; - scoped_ptr<gfx::Image> image(CreateImage(gfx::Size(kBorder, kBorder))); - - ImageGrid grid; - grid.SetImages(NULL, image.get(), NULL, - NULL, NULL, NULL, - NULL, NULL, NULL); - - ImageGrid::TestAPI test_api(&grid); - EXPECT_TRUE(grid.top_left_layer() == NULL); - ASSERT_TRUE(grid.top_layer() != NULL); - EXPECT_TRUE(grid.top_right_layer() == NULL); - EXPECT_TRUE(grid.left_layer() == NULL); - EXPECT_TRUE(grid.center_layer() == NULL); - EXPECT_TRUE(grid.right_layer() == NULL); - EXPECT_TRUE(grid.bottom_left_layer() == NULL); - EXPECT_TRUE(grid.bottom_layer() == NULL); - EXPECT_TRUE(grid.bottom_right_layer() == NULL); - - const gfx::Size kSize(10, 10); - grid.SetSize(kSize); - - // The top layer should be scaled horizontally across the entire width, but it - // shouldn't be scaled vertically. - EXPECT_EQ(gfx::RectF(0, 0, kSize.width(), kBorder).ToString(), - test_api.GetTransformedLayerBounds( - *grid.top_layer()).ToString()); -} - -// Check that we don't crash when we reset existing images to NULL and -// reset NULL images to new ones. -TEST_F(ImageGridTest, ResetImages) { - const int kBorder = 1; - scoped_ptr<gfx::Image> image(CreateImage(gfx::Size(kBorder, kBorder))); - - ImageGrid grid; - grid.SetImages(NULL, image.get(), NULL, - NULL, NULL, NULL, - NULL, NULL, NULL); - - // Only the top edge has a layer. - ImageGrid::TestAPI test_api(&grid); - ASSERT_TRUE(grid.top_left_layer() == NULL); - ASSERT_FALSE(grid.top_layer() == NULL); - ASSERT_TRUE(grid.top_right_layer() == NULL); - ASSERT_TRUE(grid.left_layer() == NULL); - ASSERT_TRUE(grid.center_layer() == NULL); - ASSERT_TRUE(grid.right_layer() == NULL); - ASSERT_TRUE(grid.bottom_left_layer() == NULL); - ASSERT_TRUE(grid.bottom_layer() == NULL); - ASSERT_TRUE(grid.bottom_right_layer() == NULL); - - grid.SetImages(NULL, NULL, NULL, - NULL, NULL, NULL, - NULL, image.get(), NULL); - - // Now only the bottom edge has a layer. - ASSERT_TRUE(grid.top_left_layer() == NULL); - ASSERT_TRUE(grid.top_layer() == NULL); - ASSERT_TRUE(grid.top_right_layer() == NULL); - ASSERT_TRUE(grid.left_layer() == NULL); - ASSERT_TRUE(grid.center_layer() == NULL); - ASSERT_TRUE(grid.right_layer() == NULL); - ASSERT_TRUE(grid.bottom_left_layer() == NULL); - ASSERT_FALSE(grid.bottom_layer() == NULL); - ASSERT_TRUE(grid.bottom_right_layer() == NULL); -} - -// Test that side (top, left, right, bottom) layers that are narrower than their -// adjacent corner layers stay pinned to the outside edges instead of getting -// moved inwards or scaled. This exercises the scenario used for shadows. -TEST_F(ImageGridTest, SmallerSides) { - const int kCorner = 2; - const int kEdge = 1; - - scoped_ptr<gfx::Image> top_left_image( - CreateImage(gfx::Size(kCorner, kCorner))); - scoped_ptr<gfx::Image> top_image(CreateImage(gfx::Size(kEdge, kEdge))); - scoped_ptr<gfx::Image> top_right_image( - CreateImage(gfx::Size(kCorner, kCorner))); - scoped_ptr<gfx::Image> left_image(CreateImage(gfx::Size(kEdge, kEdge))); - scoped_ptr<gfx::Image> right_image(CreateImage(gfx::Size(kEdge, kEdge))); - - ImageGrid grid; - grid.SetImages(top_left_image.get(), top_image.get(), top_right_image.get(), - left_image.get(), NULL, right_image.get(), - NULL, NULL, NULL); - ImageGrid::TestAPI test_api(&grid); - - const gfx::Size kSize(20, 30); - grid.SetSize(kSize); - - // The top layer should be flush with the top edge and stretched horizontally - // between the two top corners. - EXPECT_EQ(gfx::RectF( - kCorner, 0, kSize.width() - 2 * kCorner, kEdge).ToString(), - test_api.GetTransformedLayerBounds( - *grid.top_layer()).ToString()); - - // The left layer should be flush with the left edge and stretched vertically - // between the top left corner and the bottom. - EXPECT_EQ(gfx::RectF( - 0, kCorner, kEdge, kSize.height() - kCorner).ToString(), - test_api.GetTransformedLayerBounds( - *grid.left_layer()).ToString()); - - // The right layer should be flush with the right edge and stretched - // vertically between the top right corner and the bottom. - EXPECT_EQ(gfx::RectF( - kSize.width() - kEdge, kCorner, - kEdge, kSize.height() - kCorner).ToString(), - test_api.GetTransformedLayerBounds( - *grid.right_layer()).ToString()); -} - -// Test that we hide or clip layers as needed when the grid is assigned a small -// size. -TEST_F(ImageGridTest, TooSmall) { - const int kCorner = 5; - const int kCenter = 3; - const int kEdge = 3; - - scoped_ptr<gfx::Image> top_left_image( - CreateImage(gfx::Size(kCorner, kCorner))); - scoped_ptr<gfx::Image> top_image(CreateImage(gfx::Size(kEdge, kEdge))); - scoped_ptr<gfx::Image> top_right_image( - CreateImage(gfx::Size(kCorner, kCorner))); - scoped_ptr<gfx::Image> left_image(CreateImage(gfx::Size(kEdge, kEdge))); - scoped_ptr<gfx::Image> center_image(CreateImage(gfx::Size(kCenter, kCenter))); - scoped_ptr<gfx::Image> right_image(CreateImage(gfx::Size(kEdge, kEdge))); - scoped_ptr<gfx::Image> bottom_left_image( - CreateImage(gfx::Size(kCorner, kCorner))); - scoped_ptr<gfx::Image> bottom_image(CreateImage(gfx::Size(kEdge, kEdge))); - scoped_ptr<gfx::Image> bottom_right_image( - CreateImage(gfx::Size(kCorner, kCorner))); - - ImageGrid grid; - grid.SetImages( - top_left_image.get(), top_image.get(), top_right_image.get(), - left_image.get(), center_image.get(), right_image.get(), - bottom_left_image.get(), bottom_image.get(), bottom_right_image.get()); - ImageGrid::TestAPI test_api(&grid); - - // Set a size that's smaller than the combined (unscaled) corner images. - const gfx::Size kSmallSize(kCorner + kCorner - 3, kCorner + kCorner - 5); - grid.SetSize(kSmallSize); - - // The scalable images around the sides and in the center should be hidden. - EXPECT_FALSE(grid.top_layer()->visible()); - EXPECT_FALSE(grid.bottom_layer()->visible()); - EXPECT_FALSE(grid.left_layer()->visible()); - EXPECT_FALSE(grid.right_layer()->visible()); - EXPECT_FALSE(grid.center_layer()->visible()); - - // The corner images' clip rects should sum to the expected size. - EXPECT_EQ(kSmallSize.width(), - test_api.top_left_clip_rect().width() + - test_api.top_right_clip_rect().width()); - EXPECT_EQ(kSmallSize.width(), - test_api.bottom_left_clip_rect().width() + - test_api.bottom_right_clip_rect().width()); - EXPECT_EQ(kSmallSize.height(), - test_api.top_left_clip_rect().height() + - test_api.bottom_left_clip_rect().height()); - EXPECT_EQ(kSmallSize.height(), - test_api.top_right_clip_rect().height() + - test_api.bottom_right_clip_rect().height()); - - // Resize the grid to be large enough to show all images. - const gfx::Size kLargeSize(kCorner + kCorner + kCenter, - kCorner + kCorner + kCenter); - grid.SetSize(kLargeSize); - - // The scalable images should be visible now. - EXPECT_TRUE(grid.top_layer()->visible()); - EXPECT_TRUE(grid.bottom_layer()->visible()); - EXPECT_TRUE(grid.left_layer()->visible()); - EXPECT_TRUE(grid.right_layer()->visible()); - EXPECT_TRUE(grid.center_layer()->visible()); - - // We shouldn't be clipping the corner images anymore. - EXPECT_TRUE(test_api.top_left_clip_rect().IsEmpty()); - EXPECT_TRUE(test_api.top_right_clip_rect().IsEmpty()); - EXPECT_TRUE(test_api.bottom_left_clip_rect().IsEmpty()); - EXPECT_TRUE(test_api.bottom_right_clip_rect().IsEmpty()); -} - -} // namespace corewm -} // namespace views diff --git a/chromium/ui/views/corewm/input_method_event_filter.cc b/chromium/ui/views/corewm/input_method_event_filter.cc deleted file mode 100644 index 8e9ead8e1d9..00000000000 --- a/chromium/ui/views/corewm/input_method_event_filter.cc +++ /dev/null @@ -1,81 +0,0 @@ -// 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. - -#include "ui/views/corewm/input_method_event_filter.h" - -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/root_window.h" -#include "ui/base/ime/input_method.h" -#include "ui/base/ime/input_method_factory.h" -#include "ui/events/event.h" - -namespace views { -namespace corewm { - -//////////////////////////////////////////////////////////////////////////////// -// InputMethodEventFilter, public: - -InputMethodEventFilter::InputMethodEventFilter(gfx::AcceleratedWidget widget) - : input_method_(ui::CreateInputMethod(this, widget)), - target_dispatcher_(NULL) { - // TODO(yusukes): Check if the root window is currently focused and pass the - // result to Init(). - input_method_->Init(true); -} - -InputMethodEventFilter::~InputMethodEventFilter() { -} - -void InputMethodEventFilter::SetInputMethodPropertyInRootWindow( - aura::Window* root_window) { - root_window->SetProperty(aura::client::kRootWindowInputMethodKey, - input_method_.get()); -} - -//////////////////////////////////////////////////////////////////////////////// -// InputMethodEventFilter, EventFilter implementation: - -void InputMethodEventFilter::OnKeyEvent(ui::KeyEvent* event) { - const ui::EventType type = event->type(); - if (type == ui::ET_TRANSLATED_KEY_PRESS || - type == ui::ET_TRANSLATED_KEY_RELEASE) { - // The |event| is already handled by this object, change the type of the - // event to ui::ET_KEY_* and pass it to the next filter. - static_cast<ui::TranslatedKeyEvent*>(event)->ConvertToKeyEvent(); - } else { - // If the focused window is changed, all requests to IME will be - // discarded so it's safe to update the target_dispatcher_ here. - aura::Window* target = static_cast<aura::Window*>(event->target()); - target_dispatcher_ = target->GetRootWindow()->GetDispatcher(); - DCHECK(target_dispatcher_); - if (input_method_->DispatchKeyEvent(*event)) - event->StopPropagation(); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// InputMethodEventFilter, ui::InputMethodDelegate implementation: - -bool InputMethodEventFilter::DispatchKeyEventPostIME( - const base::NativeEvent& event) { -#if defined(OS_WIN) - DCHECK(event.message != WM_CHAR); -#endif - ui::TranslatedKeyEvent aura_event(event, false /* is_char */); - return target_dispatcher_->AsRootWindowHostDelegate()->OnHostKeyEvent( - &aura_event); -} - -bool InputMethodEventFilter::DispatchFabricatedKeyEventPostIME( - ui::EventType type, - ui::KeyboardCode key_code, - int flags) { - ui::TranslatedKeyEvent aura_event(type == ui::ET_KEY_PRESSED, key_code, - flags); - return target_dispatcher_->AsRootWindowHostDelegate()->OnHostKeyEvent( - &aura_event); -} - -} // namespace corewm -} // namespace views diff --git a/chromium/ui/views/corewm/input_method_event_filter.h b/chromium/ui/views/corewm/input_method_event_filter.h deleted file mode 100644 index 902244c8865..00000000000 --- a/chromium/ui/views/corewm/input_method_event_filter.h +++ /dev/null @@ -1,58 +0,0 @@ -// 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. - -#ifndef UI_VIEWS_COREWM_INPUT_METHOD_EVENT_FILTER_H_ -#define UI_VIEWS_COREWM_INPUT_METHOD_EVENT_FILTER_H_ - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "base/memory/scoped_ptr.h" -#include "ui/aura/window.h" -#include "ui/base/ime/input_method_delegate.h" -#include "ui/events/event_handler.h" -#include "ui/gfx/native_widget_types.h" -#include "ui/views/views_export.h" - -namespace ui { -class InputMethod; -} - -namespace views { -namespace corewm { - -// An event filter that forwards a KeyEvent to a system IME, and dispatches a -// TranslatedKeyEvent to the root window as needed. -class VIEWS_EXPORT InputMethodEventFilter - : public ui::EventHandler, - public ui::internal::InputMethodDelegate { - public: - explicit InputMethodEventFilter(gfx::AcceleratedWidget widget); - virtual ~InputMethodEventFilter(); - - void SetInputMethodPropertyInRootWindow(aura::Window* root_window); - - ui::InputMethod* input_method() const { return input_method_.get(); } - - private: - // Overridden from ui::EventHandler: - virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE; - - // Overridden from ui::internal::InputMethodDelegate. - virtual bool DispatchKeyEventPostIME(const base::NativeEvent& event) OVERRIDE; - virtual bool DispatchFabricatedKeyEventPostIME(ui::EventType type, - ui::KeyboardCode key_code, - int flags) OVERRIDE; - - scoped_ptr<ui::InputMethod> input_method_; - - // The target dispatcher that will receive translated key events from the IME. - aura::WindowEventDispatcher* target_dispatcher_; - - DISALLOW_COPY_AND_ASSIGN(InputMethodEventFilter); -}; - -} // namespace corewm -} // namespace views - -#endif // UI_VIEWS_COREWM_INPUT_METHOD_EVENT_FILTER_H_ diff --git a/chromium/ui/views/corewm/input_method_event_filter_unittest.cc b/chromium/ui/views/corewm/input_method_event_filter_unittest.cc deleted file mode 100644 index 2c95dc44e82..00000000000 --- a/chromium/ui/views/corewm/input_method_event_filter_unittest.cc +++ /dev/null @@ -1,91 +0,0 @@ -// 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. - -#include "ui/views/corewm/input_method_event_filter.h" - -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/aura/client/activation_client.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/root_window.h" -#include "ui/views/corewm/compound_event_filter.h" -#include "ui/aura/test/aura_test_base.h" -#include "ui/aura/test/event_generator.h" -#include "ui/aura/test/test_event_handler.h" -#include "ui/aura/test/test_windows.h" - -#if !defined(OS_WIN) && !defined(USE_X11) -// On platforms except Windows and X11, aura::test::EventGenerator::PressKey -// generates a key event without native_event(), which is not supported by -// ui::MockInputMethod. -#define TestInputMethodKeyEventPropagation \ -DISABLED_TestInputMethodKeyEventPropagation -#endif - -namespace views { -namespace corewm { - -typedef aura::test::AuraTestBase InputMethodEventFilterTest; - -TEST_F(InputMethodEventFilterTest, TestInputMethodProperty) { - CompoundEventFilter* root_filter = new CompoundEventFilter; - root_window()->SetEventFilter(root_filter); - - InputMethodEventFilter input_method_event_filter( - dispatcher()->host()->GetAcceleratedWidget()); - root_filter->AddHandler(&input_method_event_filter); - - // Tests if InputMethodEventFilter adds a window property on its - // construction. - EXPECT_TRUE(root_window()->GetProperty( - aura::client::kRootWindowInputMethodKey)); - - root_filter->RemoveHandler(&input_method_event_filter); -} - -// Tests if InputMethodEventFilter dispatches a ui::ET_TRANSLATED_KEY_* event to -// the root window. -TEST_F(InputMethodEventFilterTest, TestInputMethodKeyEventPropagation) { - CompoundEventFilter* root_filter = new CompoundEventFilter; - root_window()->SetEventFilter(root_filter); - - // Add the InputMethodEventFilter before the TestEventFilter. - InputMethodEventFilter input_method_event_filter( - dispatcher()->host()->GetAcceleratedWidget()); - root_filter->AddHandler(&input_method_event_filter); - - // Add TestEventFilter to the RootWindow. - aura::test::TestEventHandler test_filter; - root_filter->AddHandler(&test_filter); - - // We need an active window. Otherwise, the root window will not forward a key - // event to event filters. - aura::test::TestWindowDelegate test_delegate; - scoped_ptr<aura::Window> window(aura::test::CreateTestWindowWithDelegate( - &test_delegate, - -1, - gfx::Rect(), - root_window())); - aura::client::GetActivationClient(root_window())->ActivateWindow( - window.get()); - - // Send a fake key event to the root window. InputMethodEventFilter, which is - // automatically set up by AshTestBase, consumes it and sends a new - // ui::ET_TRANSLATED_KEY_* event to the root window, which will be consumed by - // the test event filter. - aura::test::EventGenerator generator(root_window()); - EXPECT_EQ(0, test_filter.num_key_events()); - generator.PressKey(ui::VKEY_SPACE, 0); - EXPECT_EQ(1, test_filter.num_key_events()); - generator.ReleaseKey(ui::VKEY_SPACE, 0); - EXPECT_EQ(2, test_filter.num_key_events()); - - root_filter->RemoveHandler(&input_method_event_filter); - root_filter->RemoveHandler(&test_filter); - - // Reset window before |test_delegate| gets deleted. - window.reset(); -} - -} // namespace corewm -} // namespace views diff --git a/chromium/ui/views/corewm/native_cursor_manager.h b/chromium/ui/views/corewm/native_cursor_manager.h deleted file mode 100644 index 75e4c8580a5..00000000000 --- a/chromium/ui/views/corewm/native_cursor_manager.h +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) 2013 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_VIEWS_COREWM_NATIVE_CURSOR_MANAGER_H_ -#define UI_VIEWS_COREWM_NATIVE_CURSOR_MANAGER_H_ - -#include "base/strings/string16.h" -#include "ui/views/corewm/native_cursor_manager_delegate.h" -#include "ui/views/views_export.h" - -namespace gfx { -class Display; -} - -namespace views { -namespace corewm { - -// Interface where platforms such as Ash or Desktop aura are notified of -// requested changes to cursor state. When requested, implementer should tell -// the CursorManager of any actual state changes performed through the -// delegate. -class VIEWS_EXPORT NativeCursorManager { - public: - virtual ~NativeCursorManager() {} - - // A request to set the screen DPI. Can cause changes in the current cursor. - virtual void SetDisplay( - const gfx::Display& display, - views::corewm::NativeCursorManagerDelegate* delegate) = 0; - - // A request to set the cursor to |cursor|. At minimum, implementer should - // call NativeCursorManagerDelegate::CommitCursor() with whatever cursor is - // actually used. - virtual void SetCursor( - gfx::NativeCursor cursor, - views::corewm::NativeCursorManagerDelegate* delegate) = 0; - - // A request to set the visibility of the cursor. At minimum, implementer - // should call NativeCursorManagerDelegate::CommitVisibility() with whatever - // the visibility is. - virtual void SetVisibility( - bool visible, - views::corewm::NativeCursorManagerDelegate* delegate) = 0; - - // A request to set the scale of the cursor icon. - virtual void SetScale( - float scale, - views::corewm::NativeCursorManagerDelegate* delegate) = 0; - - // A request to set the scale of the cursor icon. - virtual void SetCursorSet( - ui::CursorSetType cursor_set, - views::corewm::NativeCursorManagerDelegate* delegate) = 0; - - // A request to set whether mouse events are disabled. At minimum, - // implementer should call NativeCursorManagerDelegate:: - // CommitMouseEventsEnabled() with whether mouse events are actually enabled. - virtual void SetMouseEventsEnabled( - bool enabled, - views::corewm::NativeCursorManagerDelegate* delegate) = 0; -}; - -} // namespace corewm -} // namespace views - -#endif // UI_VIEWS_COREWM_NATIVE_CURSOR_MANAGER_H_ diff --git a/chromium/ui/views/corewm/native_cursor_manager_delegate.h b/chromium/ui/views/corewm/native_cursor_manager_delegate.h deleted file mode 100644 index 491ab47b1b4..00000000000 --- a/chromium/ui/views/corewm/native_cursor_manager_delegate.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2013 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_VIEWS_COREWM_NATIVE_CURSOR_MANAGER_DELEGATE_H_ -#define UI_VIEWS_COREWM_NATIVE_CURSOR_MANAGER_DELEGATE_H_ - -#include "ui/base/cursor/cursor.h" -#include "ui/gfx/native_widget_types.h" -#include "ui/views/views_export.h" - -namespace views { -namespace corewm { - -// The non-public interface that CursorManager exposes to its users. This -// gives accessors to all the current state, and mutators to all the current -// state. -class VIEWS_EXPORT NativeCursorManagerDelegate { - public: - virtual ~NativeCursorManagerDelegate() {} - - // TODO(tdanderson): Possibly remove this interface. - virtual gfx::NativeCursor GetCursor() const = 0; - virtual bool IsCursorVisible() const = 0; - - virtual void CommitCursor(gfx::NativeCursor cursor) = 0; - virtual void CommitVisibility(bool visible) = 0; - virtual void CommitScale(float scale) = 0; - virtual void CommitCursorSet(ui::CursorSetType cursor_set) = 0; - virtual void CommitMouseEventsEnabled(bool enabled) = 0; -}; - -} // namespace corewm -} // namespace views - -#endif // UI_VIEWS_COREWM_NATIVE_CURSOR_MANAGER_DELEGATE_H_ diff --git a/chromium/ui/views/corewm/shadow.cc b/chromium/ui/views/corewm/shadow.cc deleted file mode 100644 index 4411c8d5637..00000000000 --- a/chromium/ui/views/corewm/shadow.cc +++ /dev/null @@ -1,195 +0,0 @@ -// 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. - -#include "ui/views/corewm/shadow.h" - -#include "grit/ui_resources.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/compositor/scoped_layer_animation_settings.h" -#include "ui/views/corewm/image_grid.h" - -namespace { - -// Shadow opacity for different styles. -const float kActiveShadowOpacity = 1.0f; -const float kInactiveShadowOpacity = 0.2f; -const float kSmallShadowOpacity = 1.0f; - -// Interior inset for different styles. -const int kActiveInteriorInset = 0; -const int kInactiveInteriorInset = 0; -const int kSmallInteriorInset = 5; - -// Duration for opacity animation in milliseconds. -const int kShadowAnimationDurationMs = 100; - -float GetOpacityForStyle(views::corewm::Shadow::Style style) { - switch (style) { - case views::corewm::Shadow::STYLE_ACTIVE: - return kActiveShadowOpacity; - case views::corewm::Shadow::STYLE_INACTIVE: - return kInactiveShadowOpacity; - case views::corewm::Shadow::STYLE_SMALL: - return kSmallShadowOpacity; - } - return 1.0f; -} - -int GetInteriorInsetForStyle(views::corewm::Shadow::Style style) { - switch (style) { - case views::corewm::Shadow::STYLE_ACTIVE: - return kActiveInteriorInset; - case views::corewm::Shadow::STYLE_INACTIVE: - return kInactiveInteriorInset; - case views::corewm::Shadow::STYLE_SMALL: - return kSmallInteriorInset; - } - return 0; -} - -} // namespace - -namespace views { -namespace corewm { - -Shadow::Shadow() : style_(STYLE_ACTIVE), interior_inset_(0) { -} - -Shadow::~Shadow() { -} - -void Shadow::Init(Style style) { - style_ = style; - image_grid_.reset(new ImageGrid); - UpdateImagesForStyle(); - image_grid_->layer()->set_name("Shadow"); - image_grid_->layer()->SetOpacity(GetOpacityForStyle(style_)); -} - -void Shadow::SetContentBounds(const gfx::Rect& content_bounds) { - content_bounds_ = content_bounds; - UpdateImageGridBounds(); -} - -ui::Layer* Shadow::layer() const { - return image_grid_->layer(); -} - -void Shadow::SetStyle(Style style) { - if (style_ == style) - return; - - Style old_style = style_; - style_ = style; - - // Stop waiting for any as yet unfinished implicit animations. - StopObservingImplicitAnimations(); - - // If we're switching to or from the small style, don't bother with - // animations. - if (style == STYLE_SMALL || old_style == STYLE_SMALL) { - UpdateImagesForStyle(); - image_grid_->layer()->SetOpacity(GetOpacityForStyle(style)); - return; - } - - // If we're becoming active, switch images now. Because the inactive image - // has a very low opacity the switch isn't noticeable and this approach - // allows us to use only a single set of shadow images at a time. - if (style == STYLE_ACTIVE) { - UpdateImagesForStyle(); - // Opacity was baked into inactive image, start opacity low to match. - image_grid_->layer()->SetOpacity(kInactiveShadowOpacity); - } - - { - // Property sets within this scope will be implicitly animated. - ui::ScopedLayerAnimationSettings settings(layer()->GetAnimator()); - settings.AddObserver(this); - settings.SetTransitionDuration( - base::TimeDelta::FromMilliseconds(kShadowAnimationDurationMs)); - switch (style_) { - case STYLE_ACTIVE: - image_grid_->layer()->SetOpacity(kActiveShadowOpacity); - break; - case STYLE_INACTIVE: - image_grid_->layer()->SetOpacity(kInactiveShadowOpacity); - break; - default: - NOTREACHED() << "Unhandled style " << style_; - break; - } - } -} - -void Shadow::OnImplicitAnimationsCompleted() { - // If we just finished going inactive, switch images. This doesn't cause - // a visual pop because the inactive image opacity is so low. - if (style_ == STYLE_INACTIVE) { - UpdateImagesForStyle(); - // Opacity is baked into inactive image, so set fully opaque. - image_grid_->layer()->SetOpacity(1.0f); - } -} - -void Shadow::UpdateImagesForStyle() { - ResourceBundle& res = ResourceBundle::GetSharedInstance(); - switch (style_) { - case STYLE_ACTIVE: - image_grid_->SetImages( - &res.GetImageNamed(IDR_AURA_SHADOW_ACTIVE_TOP_LEFT), - &res.GetImageNamed(IDR_AURA_SHADOW_ACTIVE_TOP), - &res.GetImageNamed(IDR_AURA_SHADOW_ACTIVE_TOP_RIGHT), - &res.GetImageNamed(IDR_AURA_SHADOW_ACTIVE_LEFT), - NULL, - &res.GetImageNamed(IDR_AURA_SHADOW_ACTIVE_RIGHT), - &res.GetImageNamed(IDR_AURA_SHADOW_ACTIVE_BOTTOM_LEFT), - &res.GetImageNamed(IDR_AURA_SHADOW_ACTIVE_BOTTOM), - &res.GetImageNamed(IDR_AURA_SHADOW_ACTIVE_BOTTOM_RIGHT)); - break; - case STYLE_INACTIVE: - image_grid_->SetImages( - &res.GetImageNamed(IDR_AURA_SHADOW_INACTIVE_TOP_LEFT), - &res.GetImageNamed(IDR_AURA_SHADOW_INACTIVE_TOP), - &res.GetImageNamed(IDR_AURA_SHADOW_INACTIVE_TOP_RIGHT), - &res.GetImageNamed(IDR_AURA_SHADOW_INACTIVE_LEFT), - NULL, - &res.GetImageNamed(IDR_AURA_SHADOW_INACTIVE_RIGHT), - &res.GetImageNamed(IDR_AURA_SHADOW_INACTIVE_BOTTOM_LEFT), - &res.GetImageNamed(IDR_AURA_SHADOW_INACTIVE_BOTTOM), - &res.GetImageNamed(IDR_AURA_SHADOW_INACTIVE_BOTTOM_RIGHT)); - break; - case STYLE_SMALL: - image_grid_->SetImages( - &res.GetImageNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL_TOP_LEFT), - &res.GetImageNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL_TOP), - &res.GetImageNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL_TOP_RIGHT), - &res.GetImageNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL_LEFT), - NULL, - &res.GetImageNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL_RIGHT), - &res.GetImageNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL_BOTTOM_LEFT), - &res.GetImageNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL_BOTTOM), - &res.GetImageNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL_BOTTOM_RIGHT)); - break; - default: - NOTREACHED() << "Unhandled style " << style_; - break; - } - - // Update interior inset for style. - interior_inset_ = GetInteriorInsetForStyle(style_); - - // Image sizes may have changed. - UpdateImageGridBounds(); -} - -void Shadow::UpdateImageGridBounds() { - // Update bounds based on content bounds and image sizes. - gfx::Rect image_grid_bounds = content_bounds_; - image_grid_bounds.Inset(interior_inset_, interior_inset_); - image_grid_->SetContentBounds(image_grid_bounds); -} - -} // namespace corewm -} // namespace views diff --git a/chromium/ui/views/corewm/shadow.h b/chromium/ui/views/corewm/shadow.h deleted file mode 100644 index 794ba3dbeaa..00000000000 --- a/chromium/ui/views/corewm/shadow.h +++ /dev/null @@ -1,88 +0,0 @@ -// 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. - -#ifndef UI_VIEWS_COREWM_SHADOW_H_ -#define UI_VIEWS_COREWM_SHADOW_H_ - -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" -#include "ui/compositor/layer_animation_observer.h" -#include "ui/gfx/rect.h" -#include "ui/views/views_export.h" - -namespace ui { -class Layer; -} // namespace ui - -namespace views { -namespace corewm { - -class ImageGrid; - -// Simple class that draws a drop shadow around content at given bounds. -class VIEWS_EXPORT Shadow : public ui::ImplicitAnimationObserver { - public: - enum Style { - // Active windows have more opaque shadows, shifted down to make the window - // appear "higher". - STYLE_ACTIVE, - - // Inactive windows have less opaque shadows. - STYLE_INACTIVE, - - // Small windows like tooltips and context menus have lighter, smaller - // shadows. - STYLE_SMALL, - }; - - Shadow(); - virtual ~Shadow(); - - void Init(Style style); - - // Returns |image_grid_|'s ui::Layer. This is exposed so it can be added to - // the same layer as the content and stacked below it. SetContentBounds() - // should be used to adjust the shadow's size and position (rather than - // applying transformations to this layer). - ui::Layer* layer() const; - - const gfx::Rect& content_bounds() const { return content_bounds_; } - Style style() const { return style_; } - - // Moves and resizes |image_grid_| to frame |content_bounds|. - void SetContentBounds(const gfx::Rect& content_bounds); - - // Sets the shadow's style, animating opacity as necessary. - void SetStyle(Style style); - - // ui::ImplicitAnimationObserver overrides: - virtual void OnImplicitAnimationsCompleted() OVERRIDE; - - private: - // Updates the |image_grid_| images to the current |style_|. - void UpdateImagesForStyle(); - - // Updates the |image_grid_| bounds based on its image sizes and the - // current |content_bounds_|. - void UpdateImageGridBounds(); - - // The current style, set when the transition animation starts. - Style style_; - - scoped_ptr<ImageGrid> image_grid_; - - // Bounds of the content that the shadow encloses. - gfx::Rect content_bounds_; - - // The interior inset of the shadow images. The content bounds of the image - // grid should be set to |content_bounds_| inset by this amount. - int interior_inset_; - - DISALLOW_COPY_AND_ASSIGN(Shadow); -}; - -} // namespace corewm -} // namespace views - -#endif // UI_VIEWS_COREWM_SHADOW_H_ diff --git a/chromium/ui/views/corewm/shadow_controller.cc b/chromium/ui/views/corewm/shadow_controller.cc deleted file mode 100644 index 49307d8e2d2..00000000000 --- a/chromium/ui/views/corewm/shadow_controller.cc +++ /dev/null @@ -1,273 +0,0 @@ -// 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. - -#include "ui/views/corewm/shadow_controller.h" - -#include <utility> - -#include "base/command_line.h" -#include "base/logging.h" -#include "base/memory/linked_ptr.h" -#include "base/scoped_observer.h" -#include "ui/aura/client/activation_client.h" -#include "ui/aura/env.h" -#include "ui/aura/env_observer.h" -#include "ui/aura/root_window.h" -#include "ui/aura/window.h" -#include "ui/aura/window_observer.h" -#include "ui/compositor/layer.h" -#include "ui/views/corewm/shadow.h" -#include "ui/views/corewm/shadow_types.h" - -using std::make_pair; - -namespace views { -namespace corewm { - -namespace { - -ShadowType GetShadowTypeFromWindow(aura::Window* window) { - switch (window->type()) { - case aura::client::WINDOW_TYPE_NORMAL: - case aura::client::WINDOW_TYPE_PANEL: - case aura::client::WINDOW_TYPE_MENU: - case aura::client::WINDOW_TYPE_TOOLTIP: - return SHADOW_TYPE_RECTANGULAR; - default: - break; - } - return SHADOW_TYPE_NONE; -} - -bool ShouldUseSmallShadowForWindow(aura::Window* window) { - switch (window->type()) { - case aura::client::WINDOW_TYPE_MENU: - case aura::client::WINDOW_TYPE_TOOLTIP: - return true; - default: - break; - } - return false; -} - -// Returns the shadow style to be applied to |losing_active| when it is losing -// active to |gaining_active|. |gaining_active| may be of a type that hides when -// inactive, and as such we do not want to render |losing_active| as inactive. -Shadow::Style GetShadowStyleForWindowLosingActive( - aura::Window* losing_active, - aura::Window* gaining_active) { - if (gaining_active && aura::client::GetHideOnDeactivate(gaining_active)) { - aura::Window::Windows::const_iterator it = - std::find(losing_active->transient_children().begin(), - losing_active->transient_children().end(), - gaining_active); - if (it != losing_active->transient_children().end()) - return Shadow::STYLE_ACTIVE; - } - return Shadow::STYLE_INACTIVE; -} - -} // namespace - -// ShadowController::Impl ------------------------------------------------------ - -// Real implementation of the ShadowController. ShadowController observes -// ActivationChangeObserver, which are per ActivationClient, where as there is -// only a single Impl (as it observes all window creation by way of an -// EnvObserver). -class ShadowController::Impl : - public aura::EnvObserver, - public aura::WindowObserver, - public base::RefCounted<Impl> { - public: - // Returns the singleton instance, destroyed when there are no more refs. - static Impl* GetInstance(); - - // aura::EnvObserver override: - virtual void OnWindowInitialized(aura::Window* window) OVERRIDE; - - // aura::WindowObserver overrides: - virtual void OnWindowPropertyChanged( - aura::Window* window, const void* key, intptr_t old) OVERRIDE; - virtual void OnWindowBoundsChanged( - aura::Window* window, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds) OVERRIDE; - virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE; - - private: - friend class base::RefCounted<Impl>; - friend class ShadowController; - friend class ShadowController::TestApi; - - typedef std::map<aura::Window*, linked_ptr<Shadow> > WindowShadowMap; - - Impl(); - virtual ~Impl(); - - // Forwarded from ShadowController. - void OnWindowActivated(aura::Window* gained_active, - aura::Window* lost_active); - - // Checks if |window| is visible and contains a property requesting a shadow. - bool ShouldShowShadowForWindow(aura::Window* window) const; - - // Returns |window|'s shadow from |window_shadows_|, or NULL if no shadow - // exists. - Shadow* GetShadowForWindow(aura::Window* window); - - // Updates the shadow styles for windows when activation changes. - void HandleWindowActivationChange(aura::Window* gaining_active, - aura::Window* losing_active); - - // Shows or hides |window|'s shadow as needed (creating the shadow if - // necessary). - void HandlePossibleShadowVisibilityChange(aura::Window* window); - - // Creates a new shadow for |window| and stores it in |window_shadows_|. The - // shadow's bounds are initialized and it is added to the window's layer. - void CreateShadowForWindow(aura::Window* window); - - WindowShadowMap window_shadows_; - - ScopedObserver<aura::Window, aura::WindowObserver> observer_manager_; - - static Impl* instance_; - - DISALLOW_COPY_AND_ASSIGN(Impl); -}; - -// static -ShadowController::Impl* ShadowController::Impl::instance_ = NULL; - -// static -ShadowController::Impl* ShadowController::Impl::GetInstance() { - if (!instance_) - instance_ = new Impl(); - return instance_; -} - -void ShadowController::Impl::OnWindowInitialized(aura::Window* window) { - observer_manager_.Add(window); - SetShadowType(window, GetShadowTypeFromWindow(window)); - HandlePossibleShadowVisibilityChange(window); -} - -void ShadowController::Impl::OnWindowPropertyChanged(aura::Window* window, - const void* key, - intptr_t old) { - if (key == kShadowTypeKey) { - HandlePossibleShadowVisibilityChange(window); - return; - } -} - -void ShadowController::Impl::OnWindowBoundsChanged( - aura::Window* window, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds) { - Shadow* shadow = GetShadowForWindow(window); - if (shadow) - shadow->SetContentBounds(gfx::Rect(new_bounds.size())); -} - -void ShadowController::Impl::OnWindowDestroyed(aura::Window* window) { - window_shadows_.erase(window); - observer_manager_.Remove(window); -} - -void ShadowController::Impl::OnWindowActivated(aura::Window* gained_active, - aura::Window* lost_active) { - if (gained_active) { - Shadow* shadow = GetShadowForWindow(gained_active); - if (shadow && !ShouldUseSmallShadowForWindow(gained_active)) - shadow->SetStyle(Shadow::STYLE_ACTIVE); - } - if (lost_active) { - Shadow* shadow = GetShadowForWindow(lost_active); - if (shadow && !ShouldUseSmallShadowForWindow(lost_active)) { - shadow->SetStyle(GetShadowStyleForWindowLosingActive(lost_active, - gained_active)); - } - } -} - -bool ShadowController::Impl::ShouldShowShadowForWindow( - aura::Window* window) const { - const ShadowType type = GetShadowType(window); - switch (type) { - case SHADOW_TYPE_NONE: - return false; - case SHADOW_TYPE_RECTANGULAR: - return true; - default: - NOTREACHED() << "Unknown shadow type " << type; - return false; - } -} - -Shadow* ShadowController::Impl::GetShadowForWindow(aura::Window* window) { - WindowShadowMap::const_iterator it = window_shadows_.find(window); - return it != window_shadows_.end() ? it->second.get() : NULL; -} - -void ShadowController::Impl::HandlePossibleShadowVisibilityChange( - aura::Window* window) { - const bool should_show = ShouldShowShadowForWindow(window); - Shadow* shadow = GetShadowForWindow(window); - if (shadow) - shadow->layer()->SetVisible(should_show); - else if (should_show && !shadow) - CreateShadowForWindow(window); -} - -void ShadowController::Impl::CreateShadowForWindow(aura::Window* window) { - linked_ptr<Shadow> shadow(new Shadow()); - window_shadows_.insert(make_pair(window, shadow)); - - shadow->Init(ShouldUseSmallShadowForWindow(window) ? - Shadow::STYLE_SMALL : Shadow::STYLE_ACTIVE); - shadow->SetContentBounds(gfx::Rect(window->bounds().size())); - shadow->layer()->SetVisible(ShouldShowShadowForWindow(window)); - window->layer()->Add(shadow->layer()); -} - -ShadowController::Impl::Impl() - : observer_manager_(this) { - aura::Env::GetInstance()->AddObserver(this); -} - -ShadowController::Impl::~Impl() { - DCHECK_EQ(instance_, this); - aura::Env::GetInstance()->RemoveObserver(this); - instance_ = NULL; -} - -// ShadowController ------------------------------------------------------------ - -ShadowController::ShadowController( - aura::client::ActivationClient* activation_client) - : activation_client_(activation_client), - impl_(Impl::GetInstance()) { - // Watch for window activation changes. - activation_client_->AddObserver(this); -} - -ShadowController::~ShadowController() { - activation_client_->RemoveObserver(this); -} - -void ShadowController::OnWindowActivated(aura::Window* gained_active, - aura::Window* lost_active) { - impl_->OnWindowActivated(gained_active, lost_active); -} - -// ShadowController::TestApi --------------------------------------------------- - -Shadow* ShadowController::TestApi::GetShadowForWindow(aura::Window* window) { - return controller_->impl_->GetShadowForWindow(window); -} - -} // namespace corewm -} // namespace views diff --git a/chromium/ui/views/corewm/shadow_controller.h b/chromium/ui/views/corewm/shadow_controller.h deleted file mode 100644 index 2a7e29c88e5..00000000000 --- a/chromium/ui/views/corewm/shadow_controller.h +++ /dev/null @@ -1,71 +0,0 @@ -// 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. - -#ifndef UI_VIEWS_COREWM_SHADOW_CONTROLLER_H_ -#define UI_VIEWS_COREWM_SHADOW_CONTROLLER_H_ - -#include <map> - -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "base/memory/ref_counted.h" -#include "ui/aura/client/activation_change_observer.h" -#include "ui/views/views_export.h" - -namespace aura { -class Window; -namespace client { -class ActivationClient; -} -} -namespace gfx { -class Rect; -} - -namespace views { -namespace corewm { - -class Shadow; - -// ShadowController observes changes to windows and creates and updates drop -// shadows as needed. ShadowController itself is light weight and per -// ActivationClient. ShadowController delegates to its implementation class, -// which observes all window creation. -class VIEWS_EXPORT ShadowController : - public aura::client::ActivationChangeObserver { - public: - class VIEWS_EXPORT TestApi { - public: - explicit TestApi(ShadowController* controller) : controller_(controller) {} - ~TestApi() {} - - Shadow* GetShadowForWindow(aura::Window* window); - - private: - ShadowController* controller_; // not owned - - DISALLOW_COPY_AND_ASSIGN(TestApi); - }; - - explicit ShadowController(aura::client::ActivationClient* activation_client); - virtual ~ShadowController(); - - // aura::client::ActivationChangeObserver overrides: - virtual void OnWindowActivated(aura::Window* gained_active, - aura::Window* lost_active) OVERRIDE; - - private: - class Impl; - - aura::client::ActivationClient* activation_client_; - - scoped_refptr<Impl> impl_; - - DISALLOW_COPY_AND_ASSIGN(ShadowController); -}; - -} // namespace corewm -} // namespace views - -#endif // UI_VIEWS_COREWM_SHADOW_CONTROLLER_H_ diff --git a/chromium/ui/views/corewm/shadow_controller_unittest.cc b/chromium/ui/views/corewm/shadow_controller_unittest.cc deleted file mode 100644 index 4140f7d83fb..00000000000 --- a/chromium/ui/views/corewm/shadow_controller_unittest.cc +++ /dev/null @@ -1,214 +0,0 @@ -// 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. - -#include "ui/views/corewm/shadow_controller.h" - -#include <algorithm> -#include <vector> - -#include "base/memory/scoped_ptr.h" -#include "ui/aura/client/activation_client.h" -#include "ui/aura/client/window_tree_client.h" -#include "ui/aura/root_window.h" -#include "ui/aura/test/aura_test_base.h" -#include "ui/aura/window.h" -#include "ui/compositor/layer.h" -#include "ui/views/corewm/shadow.h" -#include "ui/views/corewm/shadow_types.h" - -namespace views { -namespace corewm { - -class ShadowControllerTest : public aura::test::AuraTestBase { - public: - ShadowControllerTest() {} - virtual ~ShadowControllerTest() {} - - virtual void SetUp() OVERRIDE { - AuraTestBase::SetUp(); - aura::client::ActivationClient* activation_client = - aura::client::GetActivationClient(root_window()); - shadow_controller_.reset(new ShadowController(activation_client)); - } - virtual void TearDown() OVERRIDE { - shadow_controller_.reset(); - AuraTestBase::TearDown(); - } - - protected: - ShadowController* shadow_controller() { return shadow_controller_.get(); } - - void ActivateWindow(aura::Window* window) { - DCHECK(window); - DCHECK(window->GetRootWindow()); - aura::client::GetActivationClient(window->GetRootWindow())->ActivateWindow( - window); - } - - private: - scoped_ptr<ShadowController> shadow_controller_; - - DISALLOW_COPY_AND_ASSIGN(ShadowControllerTest); -}; - -// Tests that various methods in Window update the Shadow object as expected. -TEST_F(ShadowControllerTest, Shadow) { - scoped_ptr<aura::Window> window(new aura::Window(NULL)); - window->SetType(aura::client::WINDOW_TYPE_NORMAL); - window->Init(ui::LAYER_TEXTURED); - ParentWindow(window.get()); - - // We should create the shadow before the window is visible (the shadow's - // layer won't get drawn yet since it's a child of the window's layer). - ShadowController::TestApi api(shadow_controller()); - const Shadow* shadow = api.GetShadowForWindow(window.get()); - ASSERT_TRUE(shadow != NULL); - EXPECT_TRUE(shadow->layer()->visible()); - - // The shadow should remain visible after window visibility changes. - window->Show(); - EXPECT_TRUE(shadow->layer()->visible()); - window->Hide(); - EXPECT_TRUE(shadow->layer()->visible()); - - // If the shadow is disabled, it should be hidden. - SetShadowType(window.get(), SHADOW_TYPE_NONE); - window->Show(); - EXPECT_FALSE(shadow->layer()->visible()); - SetShadowType(window.get(), SHADOW_TYPE_RECTANGULAR); - EXPECT_TRUE(shadow->layer()->visible()); - - // The shadow's layer should be a child of the window's layer. - EXPECT_EQ(window->layer(), shadow->layer()->parent()); - - window->parent()->RemoveChild(window.get()); - aura::Window* window_ptr = window.get(); - window.reset(); - EXPECT_TRUE(api.GetShadowForWindow(window_ptr) == NULL); -} - -// Tests that the window's shadow's bounds are updated correctly. -TEST_F(ShadowControllerTest, ShadowBounds) { - scoped_ptr<aura::Window> window(new aura::Window(NULL)); - window->SetType(aura::client::WINDOW_TYPE_NORMAL); - window->Init(ui::LAYER_TEXTURED); - ParentWindow(window.get()); - window->Show(); - - const gfx::Rect kOldBounds(20, 30, 400, 300); - window->SetBounds(kOldBounds); - - // When the shadow is first created, it should use the window's size (but - // remain at the origin, since it's a child of the window's layer). - SetShadowType(window.get(), SHADOW_TYPE_RECTANGULAR); - ShadowController::TestApi api(shadow_controller()); - const Shadow* shadow = api.GetShadowForWindow(window.get()); - ASSERT_TRUE(shadow != NULL); - EXPECT_EQ(gfx::Rect(kOldBounds.size()).ToString(), - shadow->content_bounds().ToString()); - - // When we change the window's bounds, the shadow's should be updated too. - gfx::Rect kNewBounds(50, 60, 500, 400); - window->SetBounds(kNewBounds); - EXPECT_EQ(gfx::Rect(kNewBounds.size()).ToString(), - shadow->content_bounds().ToString()); -} - -// Tests that activating a window changes the shadow style. -TEST_F(ShadowControllerTest, ShadowStyle) { - ShadowController::TestApi api(shadow_controller()); - - scoped_ptr<aura::Window> window1(new aura::Window(NULL)); - window1->SetType(aura::client::WINDOW_TYPE_NORMAL); - window1->Init(ui::LAYER_TEXTURED); - ParentWindow(window1.get()); - window1->SetBounds(gfx::Rect(10, 20, 300, 400)); - window1->Show(); - ActivateWindow(window1.get()); - - // window1 is active, so style should have active appearance. - Shadow* shadow1 = api.GetShadowForWindow(window1.get()); - ASSERT_TRUE(shadow1 != NULL); - EXPECT_EQ(Shadow::STYLE_ACTIVE, shadow1->style()); - - // Create another window and activate it. - scoped_ptr<aura::Window> window2(new aura::Window(NULL)); - window2->SetType(aura::client::WINDOW_TYPE_NORMAL); - window2->Init(ui::LAYER_TEXTURED); - ParentWindow(window2.get()); - window2->SetBounds(gfx::Rect(11, 21, 301, 401)); - window2->Show(); - ActivateWindow(window2.get()); - - // window1 is now inactive, so shadow should go inactive. - Shadow* shadow2 = api.GetShadowForWindow(window2.get()); - ASSERT_TRUE(shadow2 != NULL); - EXPECT_EQ(Shadow::STYLE_INACTIVE, shadow1->style()); - EXPECT_EQ(Shadow::STYLE_ACTIVE, shadow2->style()); -} - -// Tests that we use smaller shadows for tooltips and menus. -TEST_F(ShadowControllerTest, SmallShadowsForTooltipsAndMenus) { - ShadowController::TestApi api(shadow_controller()); - - scoped_ptr<aura::Window> tooltip_window(new aura::Window(NULL)); - tooltip_window->SetType(aura::client::WINDOW_TYPE_TOOLTIP); - tooltip_window->Init(ui::LAYER_TEXTURED); - ParentWindow(tooltip_window.get()); - tooltip_window->SetBounds(gfx::Rect(10, 20, 300, 400)); - tooltip_window->Show(); - - Shadow* tooltip_shadow = api.GetShadowForWindow(tooltip_window.get()); - ASSERT_TRUE(tooltip_shadow != NULL); - EXPECT_EQ(Shadow::STYLE_SMALL, tooltip_shadow->style()); - - scoped_ptr<aura::Window> menu_window(new aura::Window(NULL)); - menu_window->SetType(aura::client::WINDOW_TYPE_MENU); - menu_window->Init(ui::LAYER_TEXTURED); - ParentWindow(menu_window.get()); - menu_window->SetBounds(gfx::Rect(10, 20, 300, 400)); - menu_window->Show(); - - Shadow* menu_shadow = api.GetShadowForWindow(tooltip_window.get()); - ASSERT_TRUE(menu_shadow != NULL); - EXPECT_EQ(Shadow::STYLE_SMALL, menu_shadow->style()); -} - -// http://crbug.com/120210 - transient parents of certain types of transients -// should not lose their shadow when they lose activation to the transient. -TEST_F(ShadowControllerTest, TransientParentKeepsActiveShadow) { - ShadowController::TestApi api(shadow_controller()); - - scoped_ptr<aura::Window> window1(new aura::Window(NULL)); - window1->SetType(aura::client::WINDOW_TYPE_NORMAL); - window1->Init(ui::LAYER_TEXTURED); - ParentWindow(window1.get()); - window1->SetBounds(gfx::Rect(10, 20, 300, 400)); - window1->Show(); - ActivateWindow(window1.get()); - - // window1 is active, so style should have active appearance. - Shadow* shadow1 = api.GetShadowForWindow(window1.get()); - ASSERT_TRUE(shadow1 != NULL); - EXPECT_EQ(Shadow::STYLE_ACTIVE, shadow1->style()); - - // Create a window that is transient to window1, and that has the 'hide on - // deactivate' property set. Upon activation, window1 should still have an - // active shadow. - scoped_ptr<aura::Window> window2(new aura::Window(NULL)); - window2->SetType(aura::client::WINDOW_TYPE_NORMAL); - window2->Init(ui::LAYER_TEXTURED); - ParentWindow(window2.get()); - window2->SetBounds(gfx::Rect(11, 21, 301, 401)); - window1->AddTransientChild(window2.get()); - aura::client::SetHideOnDeactivate(window2.get(), true); - window2->Show(); - ActivateWindow(window2.get()); - - // window1 is now inactive, but its shadow should still appear active. - EXPECT_EQ(Shadow::STYLE_ACTIVE, shadow1->style()); -} - -} // namespace corewm -} // namespace views diff --git a/chromium/ui/views/corewm/shadow_types.cc b/chromium/ui/views/corewm/shadow_types.cc deleted file mode 100644 index 1e3a937028f..00000000000 --- a/chromium/ui/views/corewm/shadow_types.cc +++ /dev/null @@ -1,25 +0,0 @@ -// 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. - -#include "ui/views/corewm/shadow_types.h" - -#include "ui/aura/window_property.h" - -DECLARE_WINDOW_PROPERTY_TYPE(views::corewm::ShadowType); - -namespace views { -namespace corewm { - -void SetShadowType(aura::Window* window, ShadowType shadow_type) { - window->SetProperty(kShadowTypeKey, shadow_type); -} - -ShadowType GetShadowType(aura::Window* window) { - return window->GetProperty(kShadowTypeKey); -} - -DEFINE_WINDOW_PROPERTY_KEY(ShadowType, kShadowTypeKey, SHADOW_TYPE_NONE); - -} // namespace corewm -} // namespace views diff --git a/chromium/ui/views/corewm/shadow_types.h b/chromium/ui/views/corewm/shadow_types.h deleted file mode 100644 index 046ad705a3a..00000000000 --- a/chromium/ui/views/corewm/shadow_types.h +++ /dev/null @@ -1,36 +0,0 @@ -// 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. - -#ifndef UI_VIEWS_COREWM_SHADOW_TYPES_H_ -#define UI_VIEWS_COREWM_SHADOW_TYPES_H_ - -#include "ui/aura/window.h" -#include "ui/views/views_export.h" - -namespace aura { -class Window; -} - -namespace views { -namespace corewm { - -// Different types of drop shadows that can be drawn under a window by the -// shell. Used as a value for the kShadowTypeKey property. -enum ShadowType { - // Starts at 0 due to the cast in GetShadowType(). - SHADOW_TYPE_NONE = 0, - SHADOW_TYPE_RECTANGULAR, -}; - -VIEWS_EXPORT void SetShadowType(aura::Window* window, ShadowType shadow_type); -VIEWS_EXPORT ShadowType GetShadowType(aura::Window* window); - -// A property key describing the drop shadow that should be displayed under the -// window. If unset, no shadow is displayed. -extern const aura::WindowProperty<ShadowType>* const kShadowTypeKey; - -} // namespace corewm -} // namespace views - -#endif // UI_VIEWS_COREWM_SHADOW_TYPES_H_ diff --git a/chromium/ui/views/corewm/tooltip.h b/chromium/ui/views/corewm/tooltip.h index f714ac9a57c..7fb15bc32ca 100644 --- a/chromium/ui/views/corewm/tooltip.h +++ b/chromium/ui/views/corewm/tooltip.h @@ -27,7 +27,7 @@ class VIEWS_EXPORT Tooltip { // Updates the text on the tooltip and resizes to fit. virtual void SetText(aura::Window* window, - const string16& tooltip_text, + const base::string16& tooltip_text, const gfx::Point& location) = 0; // Shows the tooltip at the specified location (in screen coordinates). diff --git a/chromium/ui/views/corewm/tooltip_aura.cc b/chromium/ui/views/corewm/tooltip_aura.cc index 7c11bd80bbc..f9f41b93722 100644 --- a/chromium/ui/views/corewm/tooltip_aura.cc +++ b/chromium/ui/views/corewm/tooltip_aura.cc @@ -4,23 +4,20 @@ #include "ui/views/corewm/tooltip_aura.h" -#include "base/command_line.h" #include "base/strings/string_split.h" -#include "ui/aura/root_window.h" #include "ui/aura/window.h" +#include "ui/aura/window_tree_host.h" #include "ui/base/resource/resource_bundle.h" #include "ui/gfx/screen.h" #include "ui/gfx/text_elider.h" +#include "ui/gfx/text_utils.h" +#include "ui/native_theme/native_theme.h" #include "ui/views/background.h" #include "ui/views/border.h" -#include "ui/views/corewm/corewm_switches.h" #include "ui/views/widget/widget.h" namespace { -const SkColor kTooltipBackground = 0xFFFFFFCC; -const SkColor kTooltipBorder = 0xFF646450; -const int kTooltipBorderWidth = 1; const int kTooltipHorizontalPadding = 3; // Max visual tooltip width. If a tooltip is greater than this width, it will @@ -53,13 +50,6 @@ views::Widget* CreateTooltipWidget(aura::Window* tooltip_window) { return widget; } -gfx::Font GetDefaultFont() { - // TODO(varunjain): implementation duplicated in tooltip_manager_aura. Figure - // out a way to merge. - return ui::ResourceBundle::GetSharedInstance().GetFont( - ui::ResourceBundle::BaseFont); -} - } // namespace namespace views { @@ -69,13 +59,6 @@ TooltipAura::TooltipAura(gfx::ScreenType screen_type) : screen_type_(screen_type), widget_(NULL), tooltip_window_(NULL) { - label_.set_background( - views::Background::CreateSolidBackground(kTooltipBackground)); - if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoDropShadows)) { - label_.set_border( - views::Border::CreateSolidBorder(kTooltipBorderWidth, - kTooltipBorder)); - } label_.set_owned_by_client(); label_.SetMultiLine(true); } @@ -85,8 +68,9 @@ TooltipAura::~TooltipAura() { } // static -void TooltipAura::TrimTooltipToFit(int max_width, - string16* text, +void TooltipAura::TrimTooltipToFit(const gfx::FontList& font_list, + int max_width, + base::string16* text, int* width, int* line_count) { *width = 0; @@ -95,27 +79,26 @@ void TooltipAura::TrimTooltipToFit(int max_width, // Determine the available width for the tooltip. int available_width = std::min(kTooltipMaxWidthPixels, max_width); - std::vector<string16> lines; + std::vector<base::string16> lines; base::SplitString(*text, '\n', &lines); - std::vector<string16> result_lines; + std::vector<base::string16> result_lines; // Format each line to fit. - gfx::Font font = GetDefaultFont(); - for (std::vector<string16>::iterator l = lines.begin(); l != lines.end(); - ++l) { + for (std::vector<base::string16>::iterator l = lines.begin(); + l != lines.end(); ++l) { // We break the line at word boundaries, then stuff as many words as we can // in the available width to the current line, and move the remaining words // to a new line. - std::vector<string16> words; + std::vector<base::string16> words; base::SplitStringDontTrim(*l, ' ', &words); int current_width = 0; - string16 line; - for (std::vector<string16>::iterator w = words.begin(); w != words.end(); - ++w) { - string16 word = *w; + base::string16 line; + for (std::vector<base::string16>::iterator w = words.begin(); + w != words.end(); ++w) { + base::string16 word = *w; if (w + 1 != words.end()) word.push_back(' '); - int word_width = font.GetStringWidth(word); + int word_width = gfx::GetStringWidth(word, font_list); if (current_width + word_width > available_width) { // Current width will exceed the available width. Must start a new line. if (!line.empty()) @@ -139,19 +122,19 @@ void TooltipAura::TrimTooltipToFit(int max_width, *line_count = result_lines.size(); // Flatten the result. - string16 result; - for (std::vector<string16>::iterator l = result_lines.begin(); + base::string16 result; + for (std::vector<base::string16>::iterator l = result_lines.begin(); l != result_lines.end(); ++l) { if (!result.empty()) result.push_back('\n'); - int line_width = font.GetStringWidth(*l); + int line_width = gfx::GetStringWidth(*l, font_list); // Since we only break at word boundaries, it could happen that due to some // very long word, line_width is greater than the available_width. In such // case, we simply truncate at available_width and add ellipses at the end. if (line_width > available_width) { *width = available_width; - result.append(gfx::ElideText(*l, font, available_width, - gfx::ELIDE_AT_END)); + result.append(gfx::ElideText(*l, font_list, available_width, + gfx::ELIDE_TAIL)); } else { *width = std::max(*width, line_width); result.append(*l); @@ -163,25 +146,9 @@ void TooltipAura::TrimTooltipToFit(int max_width, int TooltipAura::GetMaxWidth(const gfx::Point& location) const { // TODO(varunjain): implementation duplicated in tooltip_manager_aura. Figure // out a way to merge. - gfx::Rect display_bounds = GetBoundsForTooltip(location); - return (display_bounds.width() + 1) / 2; -} - -gfx::Rect TooltipAura::GetBoundsForTooltip( - const gfx::Point& origin) const { - DCHECK(tooltip_window_); - gfx::Rect widget_bounds; - // For Desktop aura we constrain the tooltip to the bounds of the Widget - // (which comes from the RootWindow). - if (screen_type_ == gfx::SCREEN_TYPE_NATIVE && - gfx::SCREEN_TYPE_NATIVE != gfx::SCREEN_TYPE_ALTERNATE) { - widget_bounds = tooltip_window_->GetDispatcher()->host()->GetBounds(); - } gfx::Screen* screen = gfx::Screen::GetScreenByType(screen_type_); - gfx::Rect bounds(screen->GetDisplayNearestPoint(origin).bounds()); - if (!widget_bounds.IsEmpty()) - bounds.Intersect(widget_bounds); - return bounds; + gfx::Rect display_bounds(screen->GetDisplayNearestPoint(location).bounds()); + return (display_bounds.width() + 1) / 2; } void TooltipAura::SetTooltipBounds(const gfx::Point& mouse_pos, @@ -191,7 +158,8 @@ void TooltipAura::SetTooltipBounds(const gfx::Point& mouse_pos, tooltip_height); tooltip_rect.Offset(kCursorOffsetX, kCursorOffsetY); - gfx::Rect display_bounds = GetBoundsForTooltip(mouse_pos); + gfx::Screen* screen = gfx::Screen::GetScreenByType(screen_type_); + gfx::Rect display_bounds(screen->GetDisplayNearestPoint(mouse_pos).bounds()); // If tooltip is out of bounds on the x axis, we simply shift it // horizontally by the offset. @@ -209,22 +177,6 @@ void TooltipAura::SetTooltipBounds(const gfx::Point& mouse_pos, widget_->SetBounds(tooltip_rect); } -void TooltipAura::CreateWidget() { - if (widget_) { - // If the window for which the tooltip is being displayed changes and if the - // tooltip window and the tooltip widget belong to different rootwindows - // then we need to recreate the tooltip widget under the active root window - // hierarchy to get it to display. - if (widget_->GetNativeWindow()->GetRootWindow() == - tooltip_window_->GetRootWindow()) - return; - DestroyWidget(); - } - widget_ = CreateTooltipWidget(tooltip_window_); - widget_->SetContentsView(&label_); - widget_->AddObserver(this); -} - void TooltipAura::DestroyWidget() { if (widget_) { widget_->RemoveObserver(this); @@ -234,29 +186,43 @@ void TooltipAura::DestroyWidget() { } void TooltipAura::SetText(aura::Window* window, - const string16& tooltip_text, + const base::string16& tooltip_text, const gfx::Point& location) { tooltip_window_ = window; int max_width, line_count; - string16 trimmed_text(tooltip_text); - TrimTooltipToFit( - GetMaxWidth(location), &trimmed_text, &max_width, &line_count); + base::string16 trimmed_text(tooltip_text); + TrimTooltipToFit(label_.font_list(), GetMaxWidth(location), &trimmed_text, + &max_width, &line_count); label_.SetText(trimmed_text); int width = max_width + 2 * kTooltipHorizontalPadding; int height = label_.GetHeightForWidth(max_width) + 2 * kTooltipVerticalPadding; - if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoDropShadows)) { - width += 2 * kTooltipBorderWidth; - height += 2 * kTooltipBorderWidth; + + if (!widget_) { + widget_ = CreateTooltipWidget(tooltip_window_); + widget_->SetContentsView(&label_); + widget_->AddObserver(this); } - CreateWidget(); + SetTooltipBounds(location, width, height); + + ui::NativeTheme* native_theme = widget_->GetNativeTheme(); + label_.set_background( + views::Background::CreateSolidBackground( + native_theme->GetSystemColor( + ui::NativeTheme::kColorId_TooltipBackground))); + + label_.SetAutoColorReadabilityEnabled(false); + label_.SetEnabledColor(native_theme->GetSystemColor( + ui::NativeTheme::kColorId_TooltipText)); } void TooltipAura::Show() { - if (widget_) + if (widget_) { widget_->Show(); + widget_->StackAtTop(); + } } void TooltipAura::Hide() { diff --git a/chromium/ui/views/corewm/tooltip_aura.h b/chromium/ui/views/corewm/tooltip_aura.h index 97f3737aa8e..ead119f5d95 100644 --- a/chromium/ui/views/corewm/tooltip_aura.h +++ b/chromium/ui/views/corewm/tooltip_aura.h @@ -10,6 +10,10 @@ #include "ui/views/corewm/tooltip.h" #include "ui/views/widget/widget_observer.h" +namespace gfx { +class FontList; +} // namespace gfx + namespace views { class Widget; @@ -24,11 +28,11 @@ class VIEWS_EXPORT TooltipAura : public Tooltip, public WidgetObserver { // Trims the tooltip to fit in the width |max_width|, setting |text| to the // clipped result, |width| to the width (in pixels) of the clipped text - // and |line_count| to the number of lines of text in the tooltip. |x| and |y| - // give the location of the tooltip in screen coordinates. |max_width| comes - // from GetMaxWidth(). - static void TrimTooltipToFit(int max_width, - string16* text, + // and |line_count| to the number of lines of text in the tooltip. |font_list| + // is used to layout |text|. |max_width| comes from GetMaxWidth(). + static void TrimTooltipToFit(const gfx::FontList& font_list, + int max_width, + base::string16* text, int* width, int* line_count); @@ -36,24 +40,18 @@ class VIEWS_EXPORT TooltipAura : public Tooltip, public WidgetObserver { // Returns the max width of the tooltip when shown at the specified location. int GetMaxWidth(const gfx::Point& location) const; - // Returns the bounds to fit the tooltip in. - gfx::Rect GetBoundsForTooltip(const gfx::Point& origin) const; - // Adjusts the bounds given by the arguments to fit inside the desktop // and applies the adjusted bounds to the label_. void SetTooltipBounds(const gfx::Point& mouse_pos, int tooltip_width, int tooltip_height); - // Makes sure |widget_| is valid, creating as necessary. - void CreateWidget(); - // Destroys |widget_|. void DestroyWidget(); // Tooltip: virtual void SetText(aura::Window* window, - const string16& tooltip_text, + const base::string16& tooltip_text, const gfx::Point& location) OVERRIDE; virtual void Show() OVERRIDE; virtual void Hide() OVERRIDE; diff --git a/chromium/ui/views/corewm/tooltip_aura_unittest.cc b/chromium/ui/views/corewm/tooltip_aura_unittest.cc index 75814abcad8..1e8981ad791 100644 --- a/chromium/ui/views/corewm/tooltip_aura_unittest.cc +++ b/chromium/ui/views/corewm/tooltip_aura_unittest.cc @@ -5,43 +5,44 @@ #include "ui/views/corewm/tooltip_aura.h" #include "base/strings/utf_string_conversions.h" +#include "ui/aura/test/aura_test_base.h" #include "ui/base/resource/resource_bundle.h" -#include "ui/gfx/font.h" +#include "ui/gfx/font_list.h" #include "ui/gfx/text_elider.h" -#include "ui/views/test/views_test_base.h" +#include "ui/gfx/text_utils.h" + +using base::ASCIIToUTF16; +using base::UTF8ToUTF16; namespace views { namespace corewm { -typedef ViewsTestBase TooltipAuraTest; - -// TODO(sky): clean this up. -gfx::Font GetDefaultFont() { - return ui::ResourceBundle::GetSharedInstance().GetFont( - ui::ResourceBundle::BaseFont); -} +typedef aura::test::AuraTestBase TooltipAuraTest; TEST_F(TooltipAuraTest, TrimTooltipToFitTests) { + const gfx::FontList font_list; const int max_width = 4000; - string16 tooltip; + base::string16 tooltip; int width, line_count, expect_lines; int max_pixel_width = 400; // copied from constants in tooltip_controller.cc int max_lines = 10; // copied from constants in tooltip_controller.cc - gfx::Font font = GetDefaultFont(); size_t tooltip_len; // Error in computed size vs. expected size should not be greater than the // size of the longest word. - int error_in_pixel_width = font.GetStringWidth(ASCIIToUTF16("tooltip")); + int error_in_pixel_width = gfx::GetStringWidth(ASCIIToUTF16("tooltip"), + font_list); // Long tooltips should wrap to next line tooltip.clear(); width = line_count = -1; expect_lines = 3; - for (; font.GetStringWidth(tooltip) <= (expect_lines - 1) * max_pixel_width;) + for (; gfx::GetStringWidth(tooltip, font_list) <= + (expect_lines - 1) * max_pixel_width;) tooltip.append(ASCIIToUTF16("This is part of the tooltip")); tooltip_len = tooltip.length(); - TooltipAura::TrimTooltipToFit(max_width, &tooltip, &width, &line_count); + TooltipAura::TrimTooltipToFit(font_list, max_width, &tooltip, &width, + &line_count); EXPECT_NEAR(max_pixel_width, width, error_in_pixel_width); EXPECT_EQ(expect_lines, line_count); EXPECT_EQ(tooltip_len + expect_lines - 1, tooltip.length()); @@ -50,9 +51,11 @@ TEST_F(TooltipAuraTest, TrimTooltipToFitTests) { tooltip.clear(); width = line_count = -1; expect_lines = 13; - for (; font.GetStringWidth(tooltip) <= (expect_lines - 1) * max_pixel_width;) + for (; gfx::GetStringWidth(tooltip, font_list) <= + (expect_lines - 1) * max_pixel_width;) tooltip.append(ASCIIToUTF16("This is part of the tooltip")); - TooltipAura::TrimTooltipToFit(max_width, &tooltip, &width, &line_count); + TooltipAura::TrimTooltipToFit(font_list, max_width, &tooltip, &width, + &line_count); EXPECT_NEAR(max_pixel_width, width, error_in_pixel_width); EXPECT_EQ(max_lines, line_count); @@ -60,11 +63,13 @@ TEST_F(TooltipAuraTest, TrimTooltipToFitTests) { tooltip.clear(); width = line_count = -1; expect_lines = 4; - for (; font.GetStringWidth(tooltip) <= (expect_lines - 2) * max_pixel_width;) + for (; gfx::GetStringWidth(tooltip, font_list) <= + (expect_lines - 2) * max_pixel_width;) tooltip.append(ASCIIToUTF16("This is part of the tooltip")); tooltip.insert(tooltip.length() / 2, ASCIIToUTF16("\n")); tooltip_len = tooltip.length(); - TooltipAura::TrimTooltipToFit(max_width, &tooltip, &width, &line_count); + TooltipAura::TrimTooltipToFit(font_list, max_width, &tooltip, &width, + &line_count); EXPECT_NEAR(max_pixel_width, width, error_in_pixel_width); EXPECT_EQ(expect_lines, line_count); // We may have inserted the line break above near a space which will get @@ -76,19 +81,23 @@ TEST_F(TooltipAuraTest, TrimTooltipToFitTests) { tooltip.clear(); width = line_count = -1; tooltip = UTF8ToUTF16(std::string('a', max_pixel_width)); - TooltipAura::TrimTooltipToFit(max_width, &tooltip, &width, &line_count); + TooltipAura::TrimTooltipToFit(font_list, max_width, &tooltip, &width, + &line_count); EXPECT_NEAR(max_pixel_width, width, 5); EXPECT_EQ(1, line_count); - EXPECT_EQ(gfx::ElideText(UTF8ToUTF16(std::string('a', max_pixel_width)), font, - max_pixel_width, gfx::ELIDE_AT_END), tooltip); + EXPECT_EQ(gfx::ElideText(UTF8ToUTF16(std::string('a', max_pixel_width)), + font_list, max_pixel_width, gfx::ELIDE_TAIL), + tooltip); #endif // Normal small tooltip should stay as is. tooltip.clear(); width = line_count = -1; tooltip = ASCIIToUTF16("Small Tooltip"); - TooltipAura::TrimTooltipToFit(max_width, &tooltip, &width, &line_count); - EXPECT_EQ(font.GetStringWidth(ASCIIToUTF16("Small Tooltip")), width); + TooltipAura::TrimTooltipToFit(font_list, max_width, &tooltip, &width, + &line_count); + EXPECT_EQ(gfx::GetStringWidth(ASCIIToUTF16("Small Tooltip"), font_list), + width); EXPECT_EQ(1, line_count); EXPECT_EQ(ASCIIToUTF16("Small Tooltip"), tooltip); @@ -96,10 +105,13 @@ TEST_F(TooltipAuraTest, TrimTooltipToFitTests) { tooltip.clear(); width = line_count = -1; tooltip = ASCIIToUTF16("Multi line\nTooltip"); - TooltipAura::TrimTooltipToFit(max_width, &tooltip, &width, &line_count); - int expected_width = font.GetStringWidth(ASCIIToUTF16("Multi line")); + TooltipAura::TrimTooltipToFit(font_list, max_width, &tooltip, &width, + &line_count); + int expected_width = gfx::GetStringWidth(ASCIIToUTF16("Multi line"), + font_list); expected_width = std::max(expected_width, - font.GetStringWidth(ASCIIToUTF16("Tooltip"))); + gfx::GetStringWidth(ASCIIToUTF16("Tooltip"), + font_list)); EXPECT_EQ(expected_width, width); EXPECT_EQ(2, line_count); EXPECT_EQ(ASCIIToUTF16("Multi line\nTooltip"), tooltip); @@ -108,8 +120,10 @@ TEST_F(TooltipAuraTest, TrimTooltipToFitTests) { tooltip.clear(); width = line_count = -1; tooltip = ASCIIToUTF16("Small Tool t\tip"); - TooltipAura::TrimTooltipToFit(max_width, &tooltip, &width, &line_count); - EXPECT_EQ(font.GetStringWidth(ASCIIToUTF16("Small Tool t\tip")), width); + TooltipAura::TrimTooltipToFit(font_list, max_width, &tooltip, &width, + &line_count); + EXPECT_EQ(gfx::GetStringWidth(ASCIIToUTF16("Small Tool t\tip"), font_list), + width); EXPECT_EQ(1, line_count); EXPECT_EQ(ASCIIToUTF16("Small Tool t\tip"), tooltip); } diff --git a/chromium/ui/views/corewm/tooltip_controller.cc b/chromium/ui/views/corewm/tooltip_controller.cc index b411688397d..b1ffc1c7de8 100644 --- a/chromium/ui/views/corewm/tooltip_controller.cc +++ b/chromium/ui/views/corewm/tooltip_controller.cc @@ -10,7 +10,6 @@ #include "base/time/time.h" #include "ui/aura/client/capture_client.h" #include "ui/aura/client/cursor_client.h" -#include "ui/aura/client/drag_drop_client.h" #include "ui/aura/client/screen_position_client.h" #include "ui/aura/env.h" #include "ui/aura/window.h" @@ -20,6 +19,7 @@ #include "ui/gfx/screen.h" #include "ui/views/corewm/tooltip.h" #include "ui/views/widget/tooltip_manager.h" +#include "ui/wm/public/drag_drop_client.h" namespace views { namespace corewm { @@ -115,6 +115,7 @@ aura::Window* GetTooltipTarget(const ui::MouseEvent& event, TooltipController::TooltipController(scoped_ptr<Tooltip> tooltip) : tooltip_window_(NULL), + tooltip_id_(NULL), tooltip_window_at_mouse_press_(NULL), tooltip_(tooltip.Pass()), tooltips_enabled_(true) { @@ -133,6 +134,18 @@ void TooltipController::UpdateTooltip(aura::Window* target) { if (tooltip_window_ == target && tooltip_->IsVisible()) UpdateIfRequired(); + // Reset |tooltip_window_at_mouse_press_| if the moving within the same window + // but over a region that has different tooltip text. By resetting + // |tooltip_window_at_mouse_press_| we ensure the next time the timer fires + // we'll requery for the tooltip text. + // This handles the case of clicking on a view, moving within the same window + // but over a different view, than back to the original. + if (tooltip_window_at_mouse_press_ && + target == tooltip_window_at_mouse_press_ && + aura::client::GetTooltipText(target) != tooltip_text_at_mouse_press_) { + tooltip_window_at_mouse_press_ = NULL; + } + // If we had stopped the tooltip timer for some reason, we must restart it if // there is a change in the tooltip. if (!tooltip_timer_.IsRunning()) { @@ -174,14 +187,15 @@ void TooltipController::OnMouseEvent(ui::MouseEvent* event) { case ui::ET_MOUSE_MOVED: case ui::ET_MOUSE_DRAGGED: { curr_mouse_loc_ = event->location(); - aura::Window* target = GetTooltipTarget(*event, &curr_mouse_loc_); - if (tooltip_window_ != target) { - if (tooltip_window_) - tooltip_window_->RemoveObserver(this); - tooltip_window_ = target; - if (tooltip_window_) - tooltip_window_->AddObserver(this); + aura::Window* target = NULL; + // Avoid a call to gfx::Screen::GetWindowAtScreenPoint() since it can be + // very expensive on X11 in cases when the tooltip is hidden anyway. + if (tooltips_enabled_ && + !aura::Env::GetInstance()->IsMouseButtonDown() && + !IsDragDropInProgress()) { + target = GetTooltipTarget(*event, &curr_mouse_loc_); } + SetTooltipWindow(target); if (tooltip_timer_.IsRunning()) tooltip_timer_.Reset(); @@ -214,13 +228,12 @@ void TooltipController::OnTouchEvent(ui::TouchEvent* event) { // touch events. // Hide the tooltip for touch events. tooltip_->Hide(); - if (tooltip_window_) - tooltip_window_->RemoveObserver(this); - tooltip_window_ = NULL; + SetTooltipWindow(NULL); } void TooltipController::OnCancelMode(ui::CancelModeEvent* event) { tooltip_->Hide(); + SetTooltipWindow(NULL); } void TooltipController::OnWindowDestroyed(aura::Window* window) { @@ -255,7 +268,7 @@ void TooltipController::UpdateIfRequired() { return; } - string16 tooltip_text; + base::string16 tooltip_text; if (tooltip_window_) tooltip_text = aura::client::GetTooltipText(tooltip_window_); @@ -270,12 +283,19 @@ void TooltipController::UpdateIfRequired() { tooltip_window_at_mouse_press_ = NULL; } + // If the uniqueness indicator is different from the previously encountered + // one, we should force tooltip update + const void* tooltip_id = aura::client::GetTooltipId(tooltip_window_); + bool ids_differ = false; + ids_differ = tooltip_id_ != tooltip_id; + tooltip_id_ = tooltip_id; + // We add the !tooltip_->IsVisible() below because when we come here from // TooltipTimerFired(), the tooltip_text may not have changed but we still // want to update the tooltip because the timer has fired. // If we come here from UpdateTooltip(), we have already checked for tooltip // visibility and this check below will have no effect. - if (tooltip_text_ != tooltip_text || !tooltip_->IsVisible()) { + if (tooltip_text_ != tooltip_text || !tooltip_->IsVisible() || ids_differ) { tooltip_shown_timer_.Stop(); tooltip_text_ = tooltip_text; base::string16 trimmed_text(tooltip_text_); @@ -283,13 +303,14 @@ void TooltipController::UpdateIfRequired() { // If the string consists entirely of whitespace, then don't both showing it // (an empty tooltip is useless). base::string16 whitespace_removed_text; - TrimWhitespace(trimmed_text, TRIM_ALL, &whitespace_removed_text); + base::TrimWhitespace(trimmed_text, base::TRIM_ALL, + &whitespace_removed_text); if (whitespace_removed_text.empty()) { tooltip_->Hide(); } else { gfx::Point widget_loc = curr_mouse_loc_ + tooltip_window_->GetBoundsInScreen().OffsetFromOrigin(); - tooltip_->SetText(tooltip_window_, trimmed_text, widget_loc); + tooltip_->SetText(tooltip_window_, whitespace_removed_text, widget_loc); tooltip_->Show(); int timeout = GetTooltipShownTimeout(); if (timeout > 0) { @@ -333,5 +354,15 @@ int TooltipController::GetTooltipShownTimeout() { return it->second; } +void TooltipController::SetTooltipWindow(aura::Window* target) { + if (tooltip_window_ == target) + return; + if (tooltip_window_) + tooltip_window_->RemoveObserver(this); + tooltip_window_ = target; + if (tooltip_window_) + tooltip_window_->AddObserver(this); +} + } // namespace corewm } // namespace views diff --git a/chromium/ui/views/corewm/tooltip_controller.h b/chromium/ui/views/corewm/tooltip_controller.h index 66b6a3224c7..e0453341f00 100644 --- a/chromium/ui/views/corewm/tooltip_controller.h +++ b/chromium/ui/views/corewm/tooltip_controller.h @@ -10,11 +10,11 @@ #include "base/memory/scoped_ptr.h" #include "base/strings/string16.h" #include "base/timer/timer.h" -#include "ui/aura/client/tooltip_client.h" #include "ui/aura/window_observer.h" #include "ui/events/event_handler.h" #include "ui/gfx/point.h" #include "ui/views/views_export.h" +#include "ui/wm/public/tooltip_client.h" namespace aura { class Window; @@ -61,7 +61,7 @@ class VIEWS_EXPORT TooltipController : public aura::client::TooltipClient, void TooltipShownTimerFired(); // Updates the tooltip if required (if there is any change in the tooltip - // text or the aura::Window. + // text, tooltip id or the aura::Window). void UpdateIfRequired(); // Only used in tests. @@ -74,8 +74,14 @@ class VIEWS_EXPORT TooltipController : public aura::client::TooltipClient, int GetTooltipShownTimeout(); + // Sets tooltip window to |target| if it is different from existing window. + // Calls RemoveObserver on the existing window if it is not NULL. + // Calls AddObserver on the new window if it is not NULL. + void SetTooltipWindow(aura::Window* target); + aura::Window* tooltip_window_; base::string16 tooltip_text_; + const void* tooltip_id_; // These fields are for tracking state when the user presses a mouse button. aura::Window* tooltip_window_at_mouse_press_; diff --git a/chromium/ui/views/corewm/tooltip_controller_test_helper.cc b/chromium/ui/views/corewm/tooltip_controller_test_helper.cc index 4794a6e73e4..f96b08dc50a 100644 --- a/chromium/ui/views/corewm/tooltip_controller_test_helper.cc +++ b/chromium/ui/views/corewm/tooltip_controller_test_helper.cc @@ -19,7 +19,7 @@ TooltipControllerTestHelper::TooltipControllerTestHelper( TooltipControllerTestHelper::~TooltipControllerTestHelper() { } -string16 TooltipControllerTestHelper::GetTooltipText() { +base::string16 TooltipControllerTestHelper::GetTooltipText() { return controller_->tooltip_text_; } @@ -55,7 +55,7 @@ TooltipTestView::~TooltipTestView() { } bool TooltipTestView::GetTooltipText(const gfx::Point& p, - string16* tooltip) const { + base::string16* tooltip) const { *tooltip = tooltip_text_; return true; } diff --git a/chromium/ui/views/corewm/tooltip_controller_test_helper.h b/chromium/ui/views/corewm/tooltip_controller_test_helper.h index 58386200000..4451ff35fec 100644 --- a/chromium/ui/views/corewm/tooltip_controller_test_helper.h +++ b/chromium/ui/views/corewm/tooltip_controller_test_helper.h @@ -31,7 +31,7 @@ class TooltipControllerTestHelper { TooltipController* controller() { return controller_; } // These are mostly cover methods for TooltipController private methods. - string16 GetTooltipText(); + base::string16 GetTooltipText(); aura::Window* GetTooltipWindow(); void FireTooltipTimer(); bool IsTooltipTimerRunning(); @@ -51,14 +51,16 @@ class TooltipTestView : public views::View { TooltipTestView(); virtual ~TooltipTestView(); - void set_tooltip_text(string16 tooltip_text) { tooltip_text_ = tooltip_text; } + void set_tooltip_text(base::string16 tooltip_text) { + tooltip_text_ = tooltip_text; + } // Overridden from views::View virtual bool GetTooltipText(const gfx::Point& p, - string16* tooltip) const OVERRIDE; + base::string16* tooltip) const OVERRIDE; private: - string16 tooltip_text_; + base::string16 tooltip_text_; DISALLOW_COPY_AND_ASSIGN(TooltipTestView); }; diff --git a/chromium/ui/views/corewm/tooltip_controller_unittest.cc b/chromium/ui/views/corewm/tooltip_controller_unittest.cc index 6ebf4b9f828..e3487ae854b 100644 --- a/chromium/ui/views/corewm/tooltip_controller_unittest.cc +++ b/chromium/ui/views/corewm/tooltip_controller_unittest.cc @@ -7,14 +7,13 @@ #include "base/strings/utf_string_conversions.h" #include "ui/aura/client/cursor_client.h" #include "ui/aura/client/screen_position_client.h" -#include "ui/aura/client/tooltip_client.h" -#include "ui/aura/client/window_types.h" #include "ui/aura/env.h" -#include "ui/aura/root_window.h" #include "ui/aura/test/aura_test_base.h" #include "ui/aura/test/event_generator.h" #include "ui/aura/test/test_screen.h" +#include "ui/aura/test/test_window_delegate.h" #include "ui/aura/window.h" +#include "ui/aura/window_event_dispatcher.h" #include "ui/base/resource/resource_bundle.h" #include "ui/gfx/font.h" #include "ui/gfx/point.h" @@ -23,9 +22,15 @@ #include "ui/gfx/text_elider.h" #include "ui/views/corewm/tooltip_aura.h" #include "ui/views/corewm/tooltip_controller_test_helper.h" +#include "ui/views/test/desktop_test_views_delegate.h" +#include "ui/views/test/test_views_delegate.h" #include "ui/views/view.h" #include "ui/views/widget/tooltip_manager.h" #include "ui/views/widget/widget.h" +#include "ui/wm/core/default_activation_client.h" +#include "ui/wm/core/wm_state.h" +#include "ui/wm/public/tooltip_client.h" +#include "ui/wm/public/window_types.h" #if defined(OS_WIN) #include "ui/base/win/scoped_ole_initializer.h" @@ -36,6 +41,8 @@ #include "ui/views/widget/desktop_aura/desktop_screen.h" #endif +using base::ASCIIToUTF16; + namespace views { namespace corewm { namespace test { @@ -72,7 +79,14 @@ class TooltipControllerTest : public aura::test::AuraTestBase { virtual ~TooltipControllerTest() {} virtual void SetUp() OVERRIDE { +#if defined(OS_CHROMEOS) + views_delegate_.reset(new TestViewsDelegate); +#else + views_delegate_.reset(new DesktopTestViewsDelegate); +#endif + aura::test::AuraTestBase::SetUp(); + new wm::DefaultActivationClient(root_window()); #if defined(OS_CHROMEOS) controller_.reset(new TooltipController( scoped_ptr<views::corewm::Tooltip>( @@ -100,6 +114,7 @@ class TooltipControllerTest : public aura::test::AuraTestBase { helper_.reset(); widget_.reset(); aura::test::AuraTestBase::TearDown(); + views_delegate_.reset(); } protected: @@ -126,6 +141,9 @@ class TooltipControllerTest : public aura::test::AuraTestBase { private: scoped_ptr<TooltipController> controller_; + + scoped_ptr<views::TestViewsDelegate> views_delegate_; + #if defined(OS_WIN) ui::ScopedOleInitializer ole_initializer_; #endif @@ -135,15 +153,15 @@ class TooltipControllerTest : public aura::test::AuraTestBase { TEST_F(TooltipControllerTest, ViewTooltip) { view_->set_tooltip_text(ASCIIToUTF16("Tooltip Text")); - EXPECT_EQ(string16(), helper_->GetTooltipText()); + EXPECT_EQ(base::string16(), helper_->GetTooltipText()); EXPECT_EQ(NULL, helper_->GetTooltipWindow()); generator_->MoveMouseToCenterOf(GetWindow()); EXPECT_EQ(GetWindow(), GetRootWindow()->GetEventHandlerForPoint( generator_->current_location())); - string16 expected_tooltip = ASCIIToUTF16("Tooltip Text"); + base::string16 expected_tooltip = ASCIIToUTF16("Tooltip Text"); EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(GetWindow())); - EXPECT_EQ(string16(), helper_->GetTooltipText()); + EXPECT_EQ(base::string16(), helper_->GetTooltipText()); EXPECT_EQ(GetWindow(), helper_->GetTooltipWindow()); // Fire tooltip timer so tooltip becomes visible. @@ -160,7 +178,7 @@ TEST_F(TooltipControllerTest, ViewTooltip) { TEST_F(TooltipControllerTest, TooltipsInMultipleViews) { view_->set_tooltip_text(ASCIIToUTF16("Tooltip Text")); - EXPECT_EQ(string16(), helper_->GetTooltipText()); + EXPECT_EQ(base::string16(), helper_->GetTooltipText()); EXPECT_EQ(NULL, helper_->GetTooltipWindow()); PrepareSecondView(); @@ -176,7 +194,7 @@ TEST_F(TooltipControllerTest, TooltipsInMultipleViews) { EXPECT_TRUE(helper_->IsTooltipVisible()); EXPECT_EQ(window, root_window->GetEventHandlerForPoint( generator_->current_location())); - string16 expected_tooltip = ASCIIToUTF16("Tooltip Text"); + base::string16 expected_tooltip = ASCIIToUTF16("Tooltip Text"); EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(window)); EXPECT_EQ(expected_tooltip, helper_->GetTooltipText()); EXPECT_EQ(window, helper_->GetTooltipWindow()); @@ -186,7 +204,7 @@ TEST_F(TooltipControllerTest, TooltipsInMultipleViews) { EXPECT_FALSE(helper_->IsTooltipVisible()); EXPECT_EQ(window, root_window->GetEventHandlerForPoint( generator_->current_location())); - string16 expected_tooltip; // = "" + base::string16 expected_tooltip; // = "" EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(window)); EXPECT_EQ(expected_tooltip, helper_->GetTooltipText()); EXPECT_EQ(window, helper_->GetTooltipWindow()); @@ -195,11 +213,11 @@ TEST_F(TooltipControllerTest, TooltipsInMultipleViews) { TEST_F(TooltipControllerTest, EnableOrDisableTooltips) { view_->set_tooltip_text(ASCIIToUTF16("Tooltip Text")); - EXPECT_EQ(string16(), helper_->GetTooltipText()); + EXPECT_EQ(base::string16(), helper_->GetTooltipText()); EXPECT_EQ(NULL, helper_->GetTooltipWindow()); generator_->MoveMouseRelativeTo(GetWindow(), view_->bounds().CenterPoint()); - string16 expected_tooltip = ASCIIToUTF16("Tooltip Text"); + base::string16 expected_tooltip = ASCIIToUTF16("Tooltip Text"); // Fire tooltip timer so tooltip becomes visible. helper_->FireTooltipTimer(); @@ -221,7 +239,7 @@ TEST_F(TooltipControllerTest, EnableOrDisableTooltips) { // Verifies tooltip isn't shown if tooltip text consists entirely of whitespace. TEST_F(TooltipControllerTest, DontShowEmptyTooltips) { view_->set_tooltip_text(ASCIIToUTF16(" ")); - EXPECT_EQ(string16(), helper_->GetTooltipText()); + EXPECT_EQ(base::string16(), helper_->GetTooltipText()); EXPECT_EQ(NULL, helper_->GetTooltipWindow()); generator_->MoveMouseRelativeTo(GetWindow(), view_->bounds().CenterPoint()); @@ -232,7 +250,7 @@ TEST_F(TooltipControllerTest, DontShowEmptyTooltips) { TEST_F(TooltipControllerTest, TooltipHidesOnKeyPressAndStaysHiddenUntilChange) { view_->set_tooltip_text(ASCIIToUTF16("Tooltip Text for view 1")); - EXPECT_EQ(string16(), helper_->GetTooltipText()); + EXPECT_EQ(base::string16(), helper_->GetTooltipText()); EXPECT_EQ(NULL, helper_->GetTooltipWindow()); TooltipTestView* view2 = PrepareSecondView(); @@ -261,7 +279,7 @@ TEST_F(TooltipControllerTest, TooltipHidesOnKeyPressAndStaysHiddenUntilChange) { EXPECT_EQ(window, GetRootWindow()->GetEventHandlerForPoint( generator_->current_location())); - string16 expected_tooltip = ASCIIToUTF16("Tooltip Text for view 1"); + base::string16 expected_tooltip = ASCIIToUTF16("Tooltip Text for view 1"); EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(window)); EXPECT_EQ(expected_tooltip, helper_->GetTooltipText()); EXPECT_EQ(window, helper_->GetTooltipWindow()); @@ -273,7 +291,7 @@ TEST_F(TooltipControllerTest, TooltipHidesOnKeyPressAndStaysHiddenUntilChange) { helper_->FireTooltipTimer(); EXPECT_TRUE(helper_->IsTooltipVisible()); EXPECT_TRUE(helper_->IsTooltipShownTimerRunning()); - string16 expected_tooltip = ASCIIToUTF16("Tooltip Text for view 2"); + base::string16 expected_tooltip = ASCIIToUTF16("Tooltip Text for view 2"); EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(window)); EXPECT_EQ(expected_tooltip, helper_->GetTooltipText()); EXPECT_EQ(window, helper_->GetTooltipWindow()); @@ -281,7 +299,7 @@ TEST_F(TooltipControllerTest, TooltipHidesOnKeyPressAndStaysHiddenUntilChange) { TEST_F(TooltipControllerTest, TooltipHidesOnTimeoutAndStaysHiddenUntilChange) { view_->set_tooltip_text(ASCIIToUTF16("Tooltip Text for view 1")); - EXPECT_EQ(string16(), helper_->GetTooltipText()); + EXPECT_EQ(base::string16(), helper_->GetTooltipText()); EXPECT_EQ(NULL, helper_->GetTooltipWindow()); TooltipTestView* view2 = PrepareSecondView(); @@ -309,7 +327,7 @@ TEST_F(TooltipControllerTest, TooltipHidesOnTimeoutAndStaysHiddenUntilChange) { EXPECT_FALSE(helper_->IsTooltipShownTimerRunning()); EXPECT_EQ(window, GetRootWindow()->GetEventHandlerForPoint( generator_->current_location())); - string16 expected_tooltip = ASCIIToUTF16("Tooltip Text for view 1"); + base::string16 expected_tooltip = ASCIIToUTF16("Tooltip Text for view 1"); EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(window)); EXPECT_EQ(expected_tooltip, helper_->GetTooltipText()); EXPECT_EQ(window, helper_->GetTooltipWindow()); @@ -321,7 +339,7 @@ TEST_F(TooltipControllerTest, TooltipHidesOnTimeoutAndStaysHiddenUntilChange) { helper_->FireTooltipTimer(); EXPECT_TRUE(helper_->IsTooltipVisible()); EXPECT_TRUE(helper_->IsTooltipShownTimerRunning()); - string16 expected_tooltip = ASCIIToUTF16("Tooltip Text for view 2"); + base::string16 expected_tooltip = ASCIIToUTF16("Tooltip Text for view 2"); EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(window)); EXPECT_EQ(expected_tooltip, helper_->GetTooltipText()); EXPECT_EQ(window, helper_->GetTooltipWindow()); @@ -331,9 +349,9 @@ TEST_F(TooltipControllerTest, TooltipHidesOnTimeoutAndStaysHiddenUntilChange) { TEST_F(TooltipControllerTest, HideOnExit) { view_->set_tooltip_text(ASCIIToUTF16("Tooltip Text")); generator_->MoveMouseToCenterOf(GetWindow()); - string16 expected_tooltip = ASCIIToUTF16("Tooltip Text"); + base::string16 expected_tooltip = ASCIIToUTF16("Tooltip Text"); EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(GetWindow())); - EXPECT_EQ(string16(), helper_->GetTooltipText()); + EXPECT_EQ(base::string16(), helper_->GetTooltipText()); EXPECT_EQ(GetWindow(), helper_->GetTooltipWindow()); // Fire tooltip timer so tooltip becomes visible. @@ -344,6 +362,44 @@ TEST_F(TooltipControllerTest, HideOnExit) { EXPECT_FALSE(helper_->IsTooltipVisible()); } +TEST_F(TooltipControllerTest, ReshowOnClickAfterEnterExit) { + // Owned by |view_|. + TooltipTestView* v1 = new TooltipTestView; + TooltipTestView* v2 = new TooltipTestView; + view_->AddChildView(v1); + view_->AddChildView(v2); + gfx::Rect view_bounds(view_->GetLocalBounds()); + view_bounds.set_height(view_bounds.height() / 2); + v1->SetBoundsRect(view_bounds); + view_bounds.set_y(view_bounds.height()); + v2->SetBoundsRect(view_bounds); + const base::string16 v1_tt(ASCIIToUTF16("v1")); + const base::string16 v2_tt(ASCIIToUTF16("v2")); + v1->set_tooltip_text(v1_tt); + v2->set_tooltip_text(v2_tt); + + gfx::Point v1_point(1, 1); + View::ConvertPointToWidget(v1, &v1_point); + generator_->MoveMouseRelativeTo(GetWindow(), v1_point); + + // Fire tooltip timer so tooltip becomes visible. + helper_->FireTooltipTimer(); + EXPECT_TRUE(helper_->IsTooltipVisible()); + EXPECT_EQ(v1_tt, helper_->GetTooltipText()); + + // Press the mouse, move to v2 and back to v1. + generator_->ClickLeftButton(); + + gfx::Point v2_point(1, 1); + View::ConvertPointToWidget(v2, &v2_point); + generator_->MoveMouseRelativeTo(GetWindow(), v2_point); + generator_->MoveMouseRelativeTo(GetWindow(), v1_point); + + helper_->FireTooltipTimer(); + EXPECT_TRUE(helper_->IsTooltipVisible()); + EXPECT_EQ(v1_tt, helper_->GetTooltipText()); +} + namespace { // Returns the index of |window| in its parent's children. @@ -419,11 +475,12 @@ class TooltipControllerCaptureTest : public TooltipControllerTest { // Verifies when capture is released the TooltipController resets state. TEST_F(TooltipControllerCaptureTest, CloseOnCaptureLost) { view_->GetWidget()->SetCapture(view_); + RunAllPendingInMessageLoop(); view_->set_tooltip_text(ASCIIToUTF16("Tooltip Text")); generator_->MoveMouseToCenterOf(GetWindow()); - string16 expected_tooltip = ASCIIToUTF16("Tooltip Text"); + base::string16 expected_tooltip = ASCIIToUTF16("Tooltip Text"); EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(GetWindow())); - EXPECT_EQ(string16(), helper_->GetTooltipText()); + EXPECT_EQ(base::string16(), helper_->GetTooltipText()); EXPECT_EQ(GetWindow(), helper_->GetTooltipWindow()); // Fire tooltip timer so tooltip becomes visible. @@ -444,8 +501,8 @@ TEST_F(TooltipControllerCaptureTest, CloseOnCaptureLost) { #endif // Verifies the correct window is found for tooltips when there is a capture. TEST_F(TooltipControllerCaptureTest, MAYBE_Capture) { - const string16 tooltip_text(ASCIIToUTF16("1")); - const string16 tooltip_text2(ASCIIToUTF16("2")); + const base::string16 tooltip_text(ASCIIToUTF16("1")); + const base::string16 tooltip_text2(ASCIIToUTF16("2")); widget_->SetBounds(gfx::Rect(0, 0, 200, 200)); view_->set_tooltip_text(tooltip_text); @@ -490,120 +547,285 @@ TEST_F(TooltipControllerCaptureTest, MAYBE_Capture) { widget2.reset(); } -#if !defined(OS_CHROMEOS) -// This test creates two top level windows and verifies that the tooltip -// displays correctly when mouse moves are dispatched to these windows. -// Additionally it also verifies that the tooltip is reparented to the new -// window when mouse moves are dispatched to it. -TEST_F(TooltipControllerTest, TooltipsInMultipleRootWindows) { - view_->set_tooltip_text(ASCIIToUTF16("Tooltip Text For RootWindow1")); - EXPECT_EQ(string16(), helper_->GetTooltipText()); - EXPECT_EQ(NULL, helper_->GetTooltipWindow()); +namespace { - aura::Window* window = GetWindow(); - aura::Window* root_window = GetRootWindow(); +class TestTooltip : public Tooltip { + public: + TestTooltip() : is_visible_(false) {} + virtual ~TestTooltip() {} - // Fire tooltip timer so tooltip becomes visible. - generator_->MoveMouseRelativeTo(window, view_->bounds().CenterPoint()); - helper_->FireTooltipTimer(); - EXPECT_TRUE(helper_->IsTooltipVisible()); - for (int i = 0; i < 49; ++i) { - generator_->MoveMouseBy(1, 0); - EXPECT_TRUE(helper_->IsTooltipVisible()); - EXPECT_EQ(window, root_window->GetEventHandlerForPoint( - generator_->current_location())); - string16 expected_tooltip = - ASCIIToUTF16("Tooltip Text For RootWindow1"); - EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(window)); - EXPECT_EQ(expected_tooltip, helper_->GetTooltipText()); - EXPECT_EQ(window, helper_->GetTooltipWindow()); + const base::string16& tooltip_text() const { return tooltip_text_; } + + // Tooltip: + virtual void SetText(aura::Window* window, + const base::string16& tooltip_text, + const gfx::Point& location) OVERRIDE { + tooltip_text_ = tooltip_text; + location_ = location; + } + virtual void Show() OVERRIDE { + is_visible_ = true; } + virtual void Hide() OVERRIDE { + is_visible_ = false; + } + virtual bool IsVisible() OVERRIDE { + return is_visible_; + } + const gfx::Point& location() { return location_; } + + private: + bool is_visible_; + base::string16 tooltip_text_; + gfx::Point location_; + + DISALLOW_COPY_AND_ASSIGN(TestTooltip); +}; + +} // namespace + +// Use for tests that don't depend upon views. +class TooltipControllerTest2 : public aura::test::AuraTestBase { + public: + TooltipControllerTest2() : test_tooltip_(new TestTooltip) {} + virtual ~TooltipControllerTest2() {} + + virtual void SetUp() OVERRIDE { + wm_state_.reset(new wm::WMState); + aura::test::AuraTestBase::SetUp(); + new wm::DefaultActivationClient(root_window()); + controller_.reset(new TooltipController( + scoped_ptr<corewm::Tooltip>(test_tooltip_))); + root_window()->AddPreTargetHandler(controller_.get()); + SetTooltipClient(root_window(), controller_.get()); + helper_.reset(new TooltipControllerTestHelper(controller_.get())); + generator_.reset(new aura::test::EventGenerator(root_window())); + } + + virtual void TearDown() OVERRIDE { + root_window()->RemovePreTargetHandler(controller_.get()); + aura::client::SetTooltipClient(root_window(), NULL); + controller_.reset(); + generator_.reset(); + helper_.reset(); + aura::test::AuraTestBase::TearDown(); + wm_state_.reset(); + } + + protected: + // Owned by |controller_|. + TestTooltip* test_tooltip_; + scoped_ptr<TooltipControllerTestHelper> helper_; + scoped_ptr<aura::test::EventGenerator> generator_; + + private: + scoped_ptr<TooltipController> controller_; + scoped_ptr<wm::WMState> wm_state_; + + DISALLOW_COPY_AND_ASSIGN(TooltipControllerTest2); +}; + +TEST_F(TooltipControllerTest2, VerifyLeadingTrailingWhitespaceStripped) { + aura::test::TestWindowDelegate test_delegate; + scoped_ptr<aura::Window> window( + CreateNormalWindow(100, root_window(), &test_delegate)); + window->SetBounds(gfx::Rect(0, 0, 300, 300)); + base::string16 tooltip_text(ASCIIToUTF16(" \nx ")); + aura::client::SetTooltipText(window.get(), &tooltip_text); + generator_->MoveMouseToCenterOf(window.get()); + helper_->FireTooltipTimer(); + EXPECT_EQ(ASCIIToUTF16("x"), test_tooltip_->tooltip_text()); +} + +// Verifies that tooltip is hidden and tooltip window closed upon cancel mode. +TEST_F(TooltipControllerTest2, CloseOnCancelMode) { + aura::test::TestWindowDelegate test_delegate; + scoped_ptr<aura::Window> window( + CreateNormalWindow(100, root_window(), &test_delegate)); + window->SetBounds(gfx::Rect(0, 0, 300, 300)); + base::string16 tooltip_text(ASCIIToUTF16("Tooltip Text")); + aura::client::SetTooltipText(window.get(), &tooltip_text); + generator_->MoveMouseToCenterOf(window.get()); - views::Widget* widget2 = CreateWidget(NULL); - widget2->SetContentsView(new View); - TooltipTestView* view2 = new TooltipTestView; - widget2->GetContentsView()->AddChildView(view2); - view2->SetBoundsRect(widget2->GetContentsView()->GetLocalBounds()); - helper_.reset(new TooltipControllerTestHelper( - GetController(widget2))); - generator_.reset(new aura::test::EventGenerator( - widget2->GetNativeWindow()->GetRootWindow())); - view2->set_tooltip_text(ASCIIToUTF16("Tooltip Text For RootWindow2")); - - aura::Window* window2 = widget2->GetNativeWindow(); - aura::Window* root_window2 = - widget2->GetNativeWindow()->GetRootWindow(); // Fire tooltip timer so tooltip becomes visible. - generator_->MoveMouseRelativeTo(window2, view2->bounds().CenterPoint()); helper_->FireTooltipTimer(); + EXPECT_TRUE(helper_->IsTooltipVisible()); - EXPECT_NE(root_window, root_window2); - EXPECT_NE(window, window2); + // Send OnCancelMode event and verify that tooltip becomes invisible and + // the tooltip window is closed. + ui::CancelModeEvent event; + helper_->controller()->OnCancelMode(&event); + EXPECT_FALSE(helper_->IsTooltipVisible()); + EXPECT_TRUE(helper_->GetTooltipWindow() == NULL); +} - for (int i = 0; i < 49; ++i) { - generator_->MoveMouseBy(1, 0); - EXPECT_TRUE(helper_->IsTooltipVisible()); - EXPECT_EQ(window2, root_window2->GetEventHandlerForPoint( - generator_->current_location())); - string16 expected_tooltip = ASCIIToUTF16("Tooltip Text For RootWindow2"); - EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(window2)); - EXPECT_EQ(expected_tooltip, helper_->GetTooltipText()); - EXPECT_EQ(window2, helper_->GetTooltipWindow()); +// Use for tests that need both views and a TestTooltip. +class TooltipControllerTest3 : public aura::test::AuraTestBase { + public: + TooltipControllerTest3() : test_tooltip_(new TestTooltip) {} + virtual ~TooltipControllerTest3() {} + + virtual void SetUp() OVERRIDE { + wm_state_.reset(new wm::WMState); + aura::test::AuraTestBase::SetUp(); + new wm::DefaultActivationClient(root_window()); + + widget_.reset(CreateWidget(root_window())); + widget_->SetContentsView(new View); + view_ = new TooltipTestView; + widget_->GetContentsView()->AddChildView(view_); + view_->SetBoundsRect(widget_->GetContentsView()->GetLocalBounds()); + + generator_.reset(new aura::test::EventGenerator(GetRootWindow())); + controller_.reset(new TooltipController( + scoped_ptr<views::corewm::Tooltip>(test_tooltip_))); + GetRootWindow()->RemovePreTargetHandler( + static_cast<TooltipController*>(aura::client::GetTooltipClient( + widget_->GetNativeWindow()->GetRootWindow()))); + GetRootWindow()->AddPreTargetHandler(controller_.get()); + helper_.reset(new TooltipControllerTestHelper(controller_.get())); + SetTooltipClient(GetRootWindow(), controller_.get()); } - bool tooltip_reparented = false; - for (size_t i = 0; i < root_window2->children().size(); ++i) { - if (root_window2->children()[i]->type() == - aura::client::WINDOW_TYPE_TOOLTIP) { - tooltip_reparented = true; - break; - } + virtual void TearDown() OVERRIDE { + GetRootWindow()->RemovePreTargetHandler(controller_.get()); + aura::client::SetTooltipClient(GetRootWindow(), NULL); + + controller_.reset(); + generator_.reset(); + helper_.reset(); + widget_.reset(); + aura::test::AuraTestBase::TearDown(); + wm_state_.reset(); } - EXPECT_TRUE(tooltip_reparented); - widget2->Close(); -} -// This test validates whether the tooltip after becoming visible stays at the -// top of the ZOrder in its root window after activation changes. -TEST_F(TooltipControllerTest, TooltipAtTopOfZOrderAfterActivation) { - view_->set_tooltip_text(ASCIIToUTF16("Tooltip Text")); - EXPECT_EQ(string16(), helper_->GetTooltipText()); - EXPECT_EQ(NULL, helper_->GetTooltipWindow()); - generator_->MoveMouseToCenterOf(GetWindow()); + aura::Window* GetWindow() { return widget_->GetNativeWindow(); } - EXPECT_EQ(GetWindow(), GetRootWindow()->GetEventHandlerForPoint( - generator_->current_location())); - string16 expected_tooltip = ASCIIToUTF16("Tooltip Text"); - EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(GetWindow())); - EXPECT_EQ(string16(), helper_->GetTooltipText()); - EXPECT_EQ(GetWindow(), helper_->GetTooltipWindow()); + protected: + // Owned by |controller_|. + TestTooltip* test_tooltip_; + scoped_ptr<TooltipControllerTestHelper> helper_; + scoped_ptr<aura::test::EventGenerator> generator_; + scoped_ptr<views::Widget> widget_; + TooltipTestView* view_; - // Fire tooltip timer so tooltip becomes visible. + private: + scoped_ptr<TooltipController> controller_; + scoped_ptr<wm::WMState> wm_state_; + +#if defined(OS_WIN) + ui::ScopedOleInitializer ole_initializer_; +#endif + + aura::Window* GetRootWindow() { return GetWindow()->GetRootWindow(); } + + DISALLOW_COPY_AND_ASSIGN(TooltipControllerTest3); +}; + +TEST_F(TooltipControllerTest3, TooltipPositionChangesOnTwoViewsWithSameLabel) { + // Owned by |view_|. + // These two views have the same tooltip text + TooltipTestView* v1 = new TooltipTestView; + TooltipTestView* v2 = new TooltipTestView; + // v1_1 is a view inside v1 that has an identical tooltip text to that of v1 + // and v2 + TooltipTestView* v1_1 = new TooltipTestView; + // v2_1 is a view inside v2 that has an identical tooltip text to that of v1 + // and v2 + TooltipTestView* v2_1 = new TooltipTestView; + // v2_2 is a view inside v2 with the tooltip text different from all the + // others + TooltipTestView* v2_2 = new TooltipTestView; + + // Setup all the views' relations + view_->AddChildView(v1); + view_->AddChildView(v2); + v1->AddChildView(v1_1); + v2->AddChildView(v2_1); + v2->AddChildView(v2_2); + const base::string16 reference_string( + base::ASCIIToUTF16("Identical Tooltip Text")); + const base::string16 alternative_string( + base::ASCIIToUTF16("Another Shrubbery")); + v1->set_tooltip_text(reference_string); + v2->set_tooltip_text(reference_string); + v1_1->set_tooltip_text(reference_string); + v2_1->set_tooltip_text(reference_string); + v2_2->set_tooltip_text(alternative_string); + + // Set views' bounds + gfx::Rect view_bounds(view_->GetLocalBounds()); + view_bounds.set_height(view_bounds.height() / 2); + v1->SetBoundsRect(view_bounds); + v1_1->SetBounds(0, 0, 3, 3); + view_bounds.set_y(view_bounds.height()); + v2->SetBoundsRect(view_bounds); + v2_2->SetBounds(view_bounds.width() - 3, view_bounds.height() - 3, 3, 3); + v2_1->SetBounds(0, 0, 3, 3); + + // Test whether a toolbar appears on v1 + gfx::Point center = v1->bounds().CenterPoint(); + generator_->MoveMouseRelativeTo(GetWindow(), center); helper_->FireTooltipTimer(); + EXPECT_TRUE(helper_->IsTooltipVisible()); + EXPECT_EQ(reference_string, helper_->GetTooltipText()); + gfx::Point tooltip_bounds1 = test_tooltip_->location(); + // Test whether the toolbar changes position on mouse over v2 + center = v2->bounds().CenterPoint(); + generator_->MoveMouseRelativeTo(GetWindow(), center); + helper_->FireTooltipTimer(); EXPECT_TRUE(helper_->IsTooltipVisible()); - generator_->MoveMouseBy(1, 0); + EXPECT_EQ(reference_string, helper_->GetTooltipText()); + gfx::Point tooltip_bounds2 = test_tooltip_->location(); + + EXPECT_NE(tooltip_bounds1, gfx::Point()); + EXPECT_NE(tooltip_bounds2, gfx::Point()); + EXPECT_NE(tooltip_bounds1, tooltip_bounds2); + + // Test if the toolbar does not change position on encountering a contained + // view with the same tooltip text + center = v2_1->GetLocalBounds().CenterPoint(); + views::View::ConvertPointToTarget(v2_1, view_, ¢er); + generator_->MoveMouseRelativeTo(GetWindow(), center); + helper_->FireTooltipTimer(); + gfx::Point tooltip_bounds2_1 = test_tooltip_->location(); + EXPECT_NE(tooltip_bounds2, tooltip_bounds2_1); EXPECT_TRUE(helper_->IsTooltipVisible()); - EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(GetWindow())); - EXPECT_EQ(expected_tooltip, helper_->GetTooltipText()); - EXPECT_EQ(GetWindow(), helper_->GetTooltipWindow()); + EXPECT_EQ(reference_string, helper_->GetTooltipText()); + + // Test if the toolbar changes position on encountering a contained + // view with a different tooltip text + center = v2_2->GetLocalBounds().CenterPoint(); + views::View::ConvertPointToTarget(v2_2, view_, ¢er); + generator_->MoveMouseRelativeTo(GetWindow(), center); + helper_->FireTooltipTimer(); + gfx::Point tooltip_bounds2_2 = test_tooltip_->location(); - // Fake activation loss and gain in the native widget. This should cause a - // ZOrder change which should not affect the position of the tooltip. - DesktopNativeWidgetAura* native_widget = - static_cast<DesktopNativeWidgetAura*>(widget_->native_widget()); - EXPECT_TRUE(native_widget != NULL); + EXPECT_NE(tooltip_bounds2_1, tooltip_bounds2_2); + EXPECT_TRUE(helper_->IsTooltipVisible()); + EXPECT_EQ(alternative_string, helper_->GetTooltipText()); - native_widget->HandleActivationChanged(false); - native_widget->HandleActivationChanged(true); + // Test if moving from a view that is contained by a larger view, both with + // the same tooltip text, does not change tooltip's position. + center = v1_1->GetLocalBounds().CenterPoint(); + views::View::ConvertPointToTarget(v1_1, view_, ¢er); + generator_->MoveMouseRelativeTo(GetWindow(), center); + helper_->FireTooltipTimer(); + gfx::Point tooltip_bounds1_1 = test_tooltip_->location(); - EXPECT_EQ( - widget_->GetNativeWindow()->GetRootWindow()->children().back()->type(), - aura::client::WINDOW_TYPE_TOOLTIP); -} + EXPECT_TRUE(helper_->IsTooltipVisible()); + EXPECT_EQ(reference_string, helper_->GetTooltipText()); -#endif + center = v1->bounds().CenterPoint(); + generator_->MoveMouseRelativeTo(GetWindow(), center); + helper_->FireTooltipTimer(); + tooltip_bounds1 = test_tooltip_->location(); + + EXPECT_NE(tooltip_bounds1_1, tooltip_bounds1); + EXPECT_EQ(reference_string, helper_->GetTooltipText()); +} } // namespace test } // namespace corewm diff --git a/chromium/ui/views/corewm/tooltip_win.cc b/chromium/ui/views/corewm/tooltip_win.cc index 10341d61635..4d2a4badb0e 100644 --- a/chromium/ui/views/corewm/tooltip_win.cc +++ b/chromium/ui/views/corewm/tooltip_win.cc @@ -12,6 +12,8 @@ #include "ui/base/l10n/l10n_util_win.h" #include "ui/gfx/rect.h" #include "ui/gfx/screen.h" +#include "ui/gfx/win/dpi.h" +#include "ui/views/corewm/cursor_height_provider_win.h" namespace views { namespace corewm { @@ -63,7 +65,7 @@ bool TooltipWin::EnsureTooltipWindow() { TOOLTIPS_CLASS, NULL, TTS_NOPREFIX | WS_POPUP, 0, 0, 0, 0, parent_hwnd_, NULL, NULL, NULL); if (!tooltip_hwnd_) { - LOG_GETLASTERROR(WARNING) << "tooltip creation failed, disabling tooltips"; + PLOG(WARNING) << "tooltip creation failed, disabling tooltips"; return false; } @@ -76,20 +78,19 @@ bool TooltipWin::EnsureTooltipWindow() { void TooltipWin::PositionTooltip() { // This code only runs for non-metro, so GetNativeScreen() is fine. - gfx::Display display( - gfx::Screen::GetNativeScreen()->GetDisplayNearestPoint(location_)); + gfx::Point screen_point = gfx::win::DIPToScreenPoint(location_); + const int cursoroffset = GetCurrentCursorVisibleHeight(); + screen_point.Offset(0, cursoroffset); DWORD tooltip_size = SendMessage(tooltip_hwnd_, TTM_GETBUBBLESIZE, 0, reinterpret_cast<LPARAM>(&toolinfo_)); - // 20 accounts for visible cursor size. I tried using SM_CYCURSOR but that's - // way too big (32 on win7 default). - // TODO(sky): figure out the right way to determine offset. - const int initial_y = location_.y(); - gfx::Rect tooltip_bounds(location_.x(), initial_y + 20, - LOWORD(tooltip_size), HIWORD(tooltip_size)); - tooltip_bounds.AdjustToFit(display.work_area()); - if (tooltip_bounds.y() < initial_y) - tooltip_bounds.set_y(initial_y - tooltip_bounds.height() - 2); + const gfx::Size size(LOWORD(tooltip_size), HIWORD(tooltip_size)); + + const gfx::Display display( + gfx::Screen::GetNativeScreen()->GetDisplayNearestPoint(screen_point)); + + gfx::Rect tooltip_bounds(screen_point, size); + tooltip_bounds.AdjustToFit(gfx::win::DIPToScreenRect(display.work_area())); SetWindowPos(tooltip_hwnd_, NULL, tooltip_bounds.x(), tooltip_bounds.y(), 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); } @@ -116,8 +117,9 @@ void TooltipWin::SetText(aura::Window* window, reinterpret_cast<LPARAM>(&toolinfo_)); // This code only runs for non-metro, so GetNativeScreen() is fine. + const gfx::Point screen_point = gfx::win::DIPToScreenPoint(location_); gfx::Display display( - gfx::Screen::GetNativeScreen()->GetDisplayNearestPoint(location_)); + gfx::Screen::GetNativeScreen()->GetDisplayNearestPoint(screen_point)); const gfx::Rect monitor_bounds = display.bounds(); int max_width = (monitor_bounds.width() + 1) / 2; SendMessage(tooltip_hwnd_, TTM_SETMAXTIPWIDTH, 0, max_width); @@ -134,7 +136,7 @@ void TooltipWin::Show() { } void TooltipWin::Hide() { - if (!EnsureTooltipWindow()) + if (!tooltip_hwnd_) return; SendMessage(tooltip_hwnd_, TTM_TRACKACTIVATE, FALSE, diff --git a/chromium/ui/views/corewm/tooltip_win.h b/chromium/ui/views/corewm/tooltip_win.h index e454aac8773..b031a3204eb 100644 --- a/chromium/ui/views/corewm/tooltip_win.h +++ b/chromium/ui/views/corewm/tooltip_win.h @@ -24,7 +24,7 @@ class VIEWS_EXPORT TooltipWin : public Tooltip { explicit TooltipWin(HWND parent); virtual ~TooltipWin(); - // HandleNotify() is forwarded from DesktopRootWindowHostWin to keep the + // HandleNotify() is forwarded from DesktopWindowTreeHostWin to keep the // native tooltip in sync. bool HandleNotify(int w_param, NMHDR* l_param, LRESULT* l_result); diff --git a/chromium/ui/views/corewm/transient_window_stacking_client.cc b/chromium/ui/views/corewm/transient_window_stacking_client.cc deleted file mode 100644 index 6a4f8ab25cb..00000000000 --- a/chromium/ui/views/corewm/transient_window_stacking_client.cc +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright (c) 2013 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/views/corewm/transient_window_stacking_client.h" - -#include <algorithm> - -using aura::Window; - -namespace views { -namespace corewm { - -namespace { - -// Populates |ancestors| with all transient ancestors of |window| that are -// siblings of |window|. Returns true if any ancestors were found, false if not. -bool GetAllTransientAncestors(Window* window, Window::Windows* ancestors) { - Window* parent = window->parent(); - for (; window; window = window->transient_parent()) { - if (window->parent() == parent) - ancestors->push_back(window); - } - return (!ancestors->empty()); -} - -// Replaces |window1| and |window2| with their possible transient ancestors that -// are still siblings (have a common transient parent). |window1| and |window2| -// are not modified if such ancestors cannot be found. -void FindCommonTransientAncestor(Window** window1, Window** window2) { - DCHECK(window1); - DCHECK(window2); - DCHECK(*window1); - DCHECK(*window2); - // Assemble chains of ancestors of both windows. - Window::Windows ancestors1; - Window::Windows ancestors2; - if (!GetAllTransientAncestors(*window1, &ancestors1) || - !GetAllTransientAncestors(*window2, &ancestors2)) { - return; - } - // Walk the two chains backwards and look for the first difference. - Window::Windows::const_reverse_iterator it1 = ancestors1.rbegin(); - Window::Windows::const_reverse_iterator it2 = ancestors2.rbegin(); - for (; it1 != ancestors1.rend() && it2 != ancestors2.rend(); ++it1, ++it2) { - if (*it1 != *it2) { - *window1 = *it1; - *window2 = *it2; - break; - } - } -} - -// Returns true if |window| has |ancestor| as a transient ancestor. A transient -// ancestor is found by following the transient parent chain of the window. -bool HasTransientAncestor(const Window* window, const Window* ancestor) { - if (window->transient_parent() == ancestor) - return true; - return window->transient_parent() ? - HasTransientAncestor(window->transient_parent(), ancestor) : false; -} - -} // namespace - -TransientWindowStackingClient::TransientWindowStackingClient() { -} - -TransientWindowStackingClient::~TransientWindowStackingClient() { -} - -void TransientWindowStackingClient::AdjustStacking( - Window** child, - Window** target, - Window::StackDirection* direction) { - // For windows that have transient children stack the transient ancestors that - // are siblings. This prevents one transient group from being inserted in the - // middle of another. - FindCommonTransientAncestor(child, target); - - // When stacking above skip to the topmost transient descendant of the target. - if (*direction == Window::STACK_ABOVE && - !HasTransientAncestor(*child, *target)) { - const Window::Windows& siblings((*child)->parent()->children()); - size_t target_i = - std::find(siblings.begin(), siblings.end(), *target) - siblings.begin(); - while (target_i + 1 < siblings.size() && - HasTransientAncestor(siblings[target_i + 1], *target)) { - ++target_i; - } - *target = siblings[target_i]; - } -} - -} // namespace corewm -} // namespace views diff --git a/chromium/ui/views/corewm/transient_window_stacking_client.h b/chromium/ui/views/corewm/transient_window_stacking_client.h deleted file mode 100644 index 19358362bcb..00000000000 --- a/chromium/ui/views/corewm/transient_window_stacking_client.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2013 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_VIEWS_COREWM_TRANSIENT_WINDOW_STACKING_CLIENT_H_ -#define UI_VIEWS_COREWM_TRANSIENT_WINDOW_STACKING_CLIENT_H_ - -#include "ui/aura/client/window_stacking_client.h" -#include "ui/views/views_export.h" - -namespace views { -namespace corewm { - -class VIEWS_EXPORT TransientWindowStackingClient - : public aura::client::WindowStackingClient { - public: - TransientWindowStackingClient(); - virtual ~TransientWindowStackingClient(); - - // WindowStackingClient: - virtual void AdjustStacking(aura::Window** child, - aura::Window** target, - aura::Window::StackDirection* direction) OVERRIDE; - - private: - DISALLOW_COPY_AND_ASSIGN(TransientWindowStackingClient); -}; - -} // namespace corewm -} // namespace views - -#endif // UI_VIEWS_COREWM_TRANSIENT_WINDOW_STACKING_CLIENT_H_ diff --git a/chromium/ui/views/corewm/transient_window_stacking_client_unittest.cc b/chromium/ui/views/corewm/transient_window_stacking_client_unittest.cc deleted file mode 100644 index a84b832e596..00000000000 --- a/chromium/ui/views/corewm/transient_window_stacking_client_unittest.cc +++ /dev/null @@ -1,175 +0,0 @@ -// Copyright (c) 2013 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/views/corewm/transient_window_stacking_client.h" - -#include "base/memory/scoped_ptr.h" -#include "ui/aura/test/aura_test_base.h" -#include "ui/aura/test/test_windows.h" - -using aura::test::ChildWindowIDsAsString; -using aura::test::CreateTestWindowWithId; -using aura::Window; - -namespace views { -namespace corewm { - -class TransientWindowStackingClientTest : public aura::test::AuraTestBase { - public: - TransientWindowStackingClientTest() {} - virtual ~TransientWindowStackingClientTest() {} - - virtual void SetUp() OVERRIDE { - AuraTestBase::SetUp(); - aura::client::SetWindowStackingClient(new TransientWindowStackingClient); - } - - virtual void TearDown() OVERRIDE { - aura::client::SetWindowStackingClient(NULL); - AuraTestBase::TearDown(); - } - - private: - DISALLOW_COPY_AND_ASSIGN(TransientWindowStackingClientTest); -}; - -// Tests that transient children are stacked as a unit when using stack above. -TEST_F(TransientWindowStackingClientTest, TransientChildrenGroupAbove) { - scoped_ptr<Window> parent(CreateTestWindowWithId(0, root_window())); - scoped_ptr<Window> w1(CreateTestWindowWithId(1, parent.get())); - Window* w11 = CreateTestWindowWithId(11, parent.get()); - scoped_ptr<Window> w2(CreateTestWindowWithId(2, parent.get())); - Window* w21 = CreateTestWindowWithId(21, parent.get()); - Window* w211 = CreateTestWindowWithId(211, parent.get()); - Window* w212 = CreateTestWindowWithId(212, parent.get()); - Window* w213 = CreateTestWindowWithId(213, parent.get()); - Window* w22 = CreateTestWindowWithId(22, parent.get()); - ASSERT_EQ(8u, parent->children().size()); - - w1->AddTransientChild(w11); // w11 is now owned by w1. - w2->AddTransientChild(w21); // w21 is now owned by w2. - w2->AddTransientChild(w22); // w22 is now owned by w2. - w21->AddTransientChild(w211); // w211 is now owned by w21. - w21->AddTransientChild(w212); // w212 is now owned by w21. - w21->AddTransientChild(w213); // w213 is now owned by w21. - EXPECT_EQ("1 11 2 21 211 212 213 22", ChildWindowIDsAsString(parent.get())); - - // Stack w1 at the top (end), this should force w11 to be last (on top of w1). - parent->StackChildAtTop(w1.get()); - EXPECT_EQ(w11, parent->children().back()); - EXPECT_EQ("2 21 211 212 213 22 1 11", ChildWindowIDsAsString(parent.get())); - - // This tests that the order in children_ array rather than in - // transient_children_ array is used when reinserting transient children. - // If transient_children_ array was used '22' would be following '21'. - parent->StackChildAtTop(w2.get()); - EXPECT_EQ(w22, parent->children().back()); - EXPECT_EQ("1 11 2 21 211 212 213 22", ChildWindowIDsAsString(parent.get())); - - parent->StackChildAbove(w11, w2.get()); - EXPECT_EQ(w11, parent->children().back()); - EXPECT_EQ("2 21 211 212 213 22 1 11", ChildWindowIDsAsString(parent.get())); - - parent->StackChildAbove(w21, w1.get()); - EXPECT_EQ(w22, parent->children().back()); - EXPECT_EQ("1 11 2 21 211 212 213 22", ChildWindowIDsAsString(parent.get())); - - parent->StackChildAbove(w21, w22); - EXPECT_EQ(w213, parent->children().back()); - EXPECT_EQ("1 11 2 22 21 211 212 213", ChildWindowIDsAsString(parent.get())); - - parent->StackChildAbove(w11, w21); - EXPECT_EQ(w11, parent->children().back()); - EXPECT_EQ("2 22 21 211 212 213 1 11", ChildWindowIDsAsString(parent.get())); - - parent->StackChildAbove(w213, w21); - EXPECT_EQ(w11, parent->children().back()); - EXPECT_EQ("2 22 21 213 211 212 1 11", ChildWindowIDsAsString(parent.get())); - - // No change when stacking a transient parent above its transient child. - parent->StackChildAbove(w21, w211); - EXPECT_EQ(w11, parent->children().back()); - EXPECT_EQ("2 22 21 213 211 212 1 11", ChildWindowIDsAsString(parent.get())); - - // This tests that the order in children_ array rather than in - // transient_children_ array is used when reinserting transient children. - // If transient_children_ array was used '22' would be following '21'. - parent->StackChildAbove(w2.get(), w1.get()); - EXPECT_EQ(w212, parent->children().back()); - EXPECT_EQ("1 11 2 22 21 213 211 212", ChildWindowIDsAsString(parent.get())); - - parent->StackChildAbove(w11, w213); - EXPECT_EQ(w11, parent->children().back()); - EXPECT_EQ("2 22 21 213 211 212 1 11", ChildWindowIDsAsString(parent.get())); -} - -// Tests that transient children are stacked as a unit when using stack below. -TEST_F(TransientWindowStackingClientTest, TransientChildrenGroupBelow) { - scoped_ptr<Window> parent(CreateTestWindowWithId(0, root_window())); - scoped_ptr<Window> w1(CreateTestWindowWithId(1, parent.get())); - Window* w11 = CreateTestWindowWithId(11, parent.get()); - scoped_ptr<Window> w2(CreateTestWindowWithId(2, parent.get())); - Window* w21 = CreateTestWindowWithId(21, parent.get()); - Window* w211 = CreateTestWindowWithId(211, parent.get()); - Window* w212 = CreateTestWindowWithId(212, parent.get()); - Window* w213 = CreateTestWindowWithId(213, parent.get()); - Window* w22 = CreateTestWindowWithId(22, parent.get()); - ASSERT_EQ(8u, parent->children().size()); - - w1->AddTransientChild(w11); // w11 is now owned by w1. - w2->AddTransientChild(w21); // w21 is now owned by w2. - w2->AddTransientChild(w22); // w22 is now owned by w2. - w21->AddTransientChild(w211); // w211 is now owned by w21. - w21->AddTransientChild(w212); // w212 is now owned by w21. - w21->AddTransientChild(w213); // w213 is now owned by w21. - EXPECT_EQ("1 11 2 21 211 212 213 22", ChildWindowIDsAsString(parent.get())); - - // Stack w2 at the bottom, this should force w11 to be last (on top of w1). - // This also tests that the order in children_ array rather than in - // transient_children_ array is used when reinserting transient children. - // If transient_children_ array was used '22' would be following '21'. - parent->StackChildAtBottom(w2.get()); - EXPECT_EQ(w11, parent->children().back()); - EXPECT_EQ("2 21 211 212 213 22 1 11", ChildWindowIDsAsString(parent.get())); - - parent->StackChildAtBottom(w1.get()); - EXPECT_EQ(w22, parent->children().back()); - EXPECT_EQ("1 11 2 21 211 212 213 22", ChildWindowIDsAsString(parent.get())); - - parent->StackChildBelow(w21, w1.get()); - EXPECT_EQ(w11, parent->children().back()); - EXPECT_EQ("2 21 211 212 213 22 1 11", ChildWindowIDsAsString(parent.get())); - - parent->StackChildBelow(w11, w2.get()); - EXPECT_EQ(w22, parent->children().back()); - EXPECT_EQ("1 11 2 21 211 212 213 22", ChildWindowIDsAsString(parent.get())); - - parent->StackChildBelow(w22, w21); - EXPECT_EQ(w213, parent->children().back()); - EXPECT_EQ("1 11 2 22 21 211 212 213", ChildWindowIDsAsString(parent.get())); - - parent->StackChildBelow(w21, w11); - EXPECT_EQ(w11, parent->children().back()); - EXPECT_EQ("2 22 21 211 212 213 1 11", ChildWindowIDsAsString(parent.get())); - - parent->StackChildBelow(w213, w211); - EXPECT_EQ(w11, parent->children().back()); - EXPECT_EQ("2 22 21 213 211 212 1 11", ChildWindowIDsAsString(parent.get())); - - // No change when stacking a transient parent below its transient child. - parent->StackChildBelow(w21, w211); - EXPECT_EQ(w11, parent->children().back()); - EXPECT_EQ("2 22 21 213 211 212 1 11", ChildWindowIDsAsString(parent.get())); - - parent->StackChildBelow(w1.get(), w2.get()); - EXPECT_EQ(w212, parent->children().back()); - EXPECT_EQ("1 11 2 22 21 213 211 212", ChildWindowIDsAsString(parent.get())); - - parent->StackChildBelow(w213, w11); - EXPECT_EQ(w11, parent->children().back()); - EXPECT_EQ("2 22 21 213 211 212 1 11", ChildWindowIDsAsString(parent.get())); -} - -} // namespace corewm -} // namespace views diff --git a/chromium/ui/views/corewm/visibility_controller.cc b/chromium/ui/views/corewm/visibility_controller.cc deleted file mode 100644 index 4542f41c669..00000000000 --- a/chromium/ui/views/corewm/visibility_controller.cc +++ /dev/null @@ -1,87 +0,0 @@ -// 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. - -#include "ui/views/corewm/visibility_controller.h" - -#include "ui/aura/window.h" -#include "ui/aura/window_property.h" -#include "ui/compositor/layer.h" -#include "ui/views/corewm/window_animations.h" - -namespace views { -namespace corewm { - -namespace { - -// Property set on all windows whose child windows' visibility changes are -// animated. -DEFINE_WINDOW_PROPERTY_KEY( - bool, kChildWindowVisibilityChangesAnimatedKey, false); - -bool ShouldAnimateWindow(aura::Window* window) { - return window->parent() && window->parent()->GetProperty( - kChildWindowVisibilityChangesAnimatedKey); -} - -} // namespace - -VisibilityController::VisibilityController() { -} - -VisibilityController::~VisibilityController() { -} - -bool VisibilityController::CallAnimateOnChildWindowVisibilityChanged( - aura::Window* window, - bool visible) { - return AnimateOnChildWindowVisibilityChanged(window, visible); -} - -void VisibilityController::UpdateLayerVisibility(aura::Window* window, - bool visible) { - bool animated = window->type() != aura::client::WINDOW_TYPE_CONTROL && - window->type() != aura::client::WINDOW_TYPE_UNKNOWN && - ShouldAnimateWindow(window); - animated = animated && - CallAnimateOnChildWindowVisibilityChanged(window, visible); - - if (!visible) { - // For window hiding animation, we want to check if the window is already - // animating, and not do SetVisible(false) if it is. - // TODO(vollick): remove this. - animated = animated || (window->layer()->GetAnimator()-> - IsAnimatingProperty(ui::LayerAnimationElement::OPACITY) && - window->layer()->GetTargetOpacity() == 0.0f); - } - - // When a window is made visible, we always make its layer visible - // immediately. When a window is hidden, the layer must be left visible and - // only made not visible once the animation is complete. - if (!animated || visible) - window->layer()->SetVisible(visible); -} - -SuspendChildWindowVisibilityAnimations::SuspendChildWindowVisibilityAnimations( - aura::Window* window) - : window_(window), - original_enabled_(window->GetProperty( - kChildWindowVisibilityChangesAnimatedKey)) { - window_->ClearProperty(kChildWindowVisibilityChangesAnimatedKey); -} - -SuspendChildWindowVisibilityAnimations:: - ~SuspendChildWindowVisibilityAnimations() { - if (original_enabled_) - window_->SetProperty(kChildWindowVisibilityChangesAnimatedKey, true); - else - window_->ClearProperty(kChildWindowVisibilityChangesAnimatedKey); -} - -void SetChildWindowVisibilityChangesAnimated(aura::Window* window) { - window->SetProperty(kChildWindowVisibilityChangesAnimatedKey, true); -} - -} // namespace corewm -} // namespace views - diff --git a/chromium/ui/views/corewm/visibility_controller.h b/chromium/ui/views/corewm/visibility_controller.h deleted file mode 100644 index ec489822f66..00000000000 --- a/chromium/ui/views/corewm/visibility_controller.h +++ /dev/null @@ -1,75 +0,0 @@ -// 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. - -#ifndef UI_VIEWS_COREWM_VISIBILITY_CONTROLLER_H_ -#define UI_VIEWS_COREWM_VISIBILITY_CONTROLLER_H_ - -#include "base/compiler_specific.h" -#include "base/logging.h" -#include "ui/aura/client/visibility_client.h" -#include "ui/views/views_export.h" - -namespace views { -namespace corewm { - -class VIEWS_EXPORT VisibilityController - : public aura::client::VisibilityClient { - public: - VisibilityController(); - virtual ~VisibilityController(); - - protected: - // Subclasses override if they want to call a different implementation of - // this function. - // TODO(beng): potentially replace by an actual window animator class in - // window_animations.h. - virtual bool CallAnimateOnChildWindowVisibilityChanged(aura::Window* window, - bool visible); - - private: - // Overridden from aura::client::VisibilityClient: - virtual void UpdateLayerVisibility(aura::Window* window, - bool visible) OVERRIDE; - - DISALLOW_COPY_AND_ASSIGN(VisibilityController); -}; - -// Suspends the animations for visibility changes during the lifetime of an -// instance of this class. -// -// Example: -// -// void ViewName::UnanimatedAction() { -// SuspendChildWindowVisibilityAnimations suspend(parent); -// // Perform unanimated action here. -// // ... -// // When the method finishes, visibility animations will return to their -// // previous state. -// } -// -class VIEWS_EXPORT SuspendChildWindowVisibilityAnimations { - public: - // Suspend visibility animations of child windows. - explicit SuspendChildWindowVisibilityAnimations(aura::Window* window); - - // Restore visibility animations to their original state. - ~SuspendChildWindowVisibilityAnimations(); - - private: - // The window to manage. - aura::Window* window_; - - // Whether the visibility animations on child windows were originally enabled. - const bool original_enabled_; - - DISALLOW_COPY_AND_ASSIGN(SuspendChildWindowVisibilityAnimations); -}; - -// Tells |window| to animate visibility changes to its children. -void VIEWS_EXPORT SetChildWindowVisibilityChangesAnimated(aura::Window* window); - -} // namespace corewm -} // namespace views - -#endif // UI_VIEWS_COREWM_VISIBILITY_CONTROLLER_H_ diff --git a/chromium/ui/views/corewm/visibility_controller_unittest.cc b/chromium/ui/views/corewm/visibility_controller_unittest.cc deleted file mode 100644 index 222d7af61e8..00000000000 --- a/chromium/ui/views/corewm/visibility_controller_unittest.cc +++ /dev/null @@ -1,57 +0,0 @@ -// 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. - -#include "ui/views/corewm/visibility_controller.h" - -#include "ui/aura/root_window.h" -#include "ui/aura/test/aura_test_base.h" -#include "ui/aura/test/test_window_delegate.h" -#include "ui/aura/test/test_windows.h" -#include "ui/aura/window.h" -#include "ui/compositor/layer.h" -#include "ui/compositor/layer_animator.h" -#include "ui/compositor/scoped_animation_duration_scale_mode.h" - -namespace views { -namespace corewm { - -typedef aura::test::AuraTestBase VisibilityControllerTest; - -// Hiding a window in an animatable container should not hide the window's layer -// immediately. -TEST_F(VisibilityControllerTest, AnimateHideDoesntHideWindowLayer) { - // We cannot disable animations for this test. - ui::ScopedAnimationDurationScaleMode normal_duration_mode( - ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION); - - VisibilityController controller; - aura::client::SetVisibilityClient(root_window(), &controller); - - SetChildWindowVisibilityChangesAnimated(root_window()); - - aura::test::TestWindowDelegate d; - scoped_ptr<aura::Window> animatable( - aura::test::CreateTestWindowWithDelegate( - &d, -2, gfx::Rect(0, 0, 50, 50), root_window())); - scoped_ptr<aura::Window> non_animatable( - aura::test::CreateTestWindowWithDelegateAndType( - &d, aura::client::WINDOW_TYPE_CONTROL, -3, gfx::Rect(51, 51, 50, 50), - root_window())); - EXPECT_TRUE(animatable->IsVisible()); - EXPECT_TRUE(animatable->layer()->visible()); - animatable->Hide(); - EXPECT_FALSE(animatable->IsVisible()); - EXPECT_TRUE(animatable->layer()->visible()); - - EXPECT_TRUE(non_animatable->IsVisible()); - EXPECT_TRUE(non_animatable->layer()->visible()); - non_animatable->Hide(); - EXPECT_FALSE(non_animatable->IsVisible()); - EXPECT_FALSE(non_animatable->layer()->visible()); - - aura::client::SetVisibilityClient(root_window(), NULL); -} - -} // namespace corewm -} // namespace views diff --git a/chromium/ui/views/corewm/window_animations.cc b/chromium/ui/views/corewm/window_animations.cc deleted file mode 100644 index 736f4bba822..00000000000 --- a/chromium/ui/views/corewm/window_animations.cc +++ /dev/null @@ -1,573 +0,0 @@ -// 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. - -#include "ui/views/corewm/window_animations.h" - -#include <math.h> - -#include <algorithm> -#include <vector> - -#include "base/command_line.h" -#include "base/compiler_specific.h" -#include "base/logging.h" -#include "base/message_loop/message_loop.h" -#include "base/stl_util.h" -#include "base/time/time.h" -#include "ui/aura/client/animation_host.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/window.h" -#include "ui/aura/window_delegate.h" -#include "ui/aura/window_observer.h" -#include "ui/aura/window_property.h" -#include "ui/compositor/compositor_observer.h" -#include "ui/compositor/layer.h" -#include "ui/compositor/layer_animation_observer.h" -#include "ui/compositor/layer_animation_sequence.h" -#include "ui/compositor/layer_animator.h" -#include "ui/compositor/scoped_layer_animation_settings.h" -#include "ui/gfx/interpolated_transform.h" -#include "ui/gfx/rect_conversions.h" -#include "ui/gfx/screen.h" -#include "ui/gfx/vector2d.h" -#include "ui/gfx/vector3d_f.h" -#include "ui/views/corewm/corewm_switches.h" -#include "ui/views/corewm/window_util.h" -#include "ui/views/view.h" -#include "ui/views/widget/widget.h" - -DECLARE_WINDOW_PROPERTY_TYPE(int) -DECLARE_WINDOW_PROPERTY_TYPE(views::corewm::WindowVisibilityAnimationType) -DECLARE_WINDOW_PROPERTY_TYPE(views::corewm::WindowVisibilityAnimationTransition) -DECLARE_WINDOW_PROPERTY_TYPE(float) -DECLARE_EXPORTED_WINDOW_PROPERTY_TYPE(VIEWS_EXPORT, bool) - -using aura::Window; -using base::TimeDelta; -using ui::Layer; - -namespace views { -namespace corewm { -namespace { -const float kWindowAnimation_Vertical_TranslateY = 15.f; -} // namespace - -DEFINE_WINDOW_PROPERTY_KEY(int, - kWindowVisibilityAnimationTypeKey, - WINDOW_VISIBILITY_ANIMATION_TYPE_DEFAULT); -DEFINE_WINDOW_PROPERTY_KEY(int, kWindowVisibilityAnimationDurationKey, 0); -DEFINE_WINDOW_PROPERTY_KEY(WindowVisibilityAnimationTransition, - kWindowVisibilityAnimationTransitionKey, - ANIMATE_BOTH); -DEFINE_WINDOW_PROPERTY_KEY(float, - kWindowVisibilityAnimationVerticalPositionKey, - kWindowAnimation_Vertical_TranslateY); - -namespace { - -const int kDefaultAnimationDurationForMenuMS = 150; - -const float kWindowAnimation_HideOpacity = 0.f; -const float kWindowAnimation_ShowOpacity = 1.f; -const float kWindowAnimation_TranslateFactor = 0.5f; -const float kWindowAnimation_ScaleFactor = .95f; - -const int kWindowAnimation_Rotate_DurationMS = 180; -const int kWindowAnimation_Rotate_OpacityDurationPercent = 90; -const float kWindowAnimation_Rotate_TranslateY = -20.f; -const float kWindowAnimation_Rotate_PerspectiveDepth = 500.f; -const float kWindowAnimation_Rotate_DegreesX = 5.f; -const float kWindowAnimation_Rotate_ScaleFactor = .99f; - -const float kWindowAnimation_Bounce_Scale = 1.02f; -const int kWindowAnimation_Bounce_DurationMS = 180; -const int kWindowAnimation_Bounce_GrowShrinkDurationPercent = 40; - -base::TimeDelta GetWindowVisibilityAnimationDuration(aura::Window* window) { - int duration = - window->GetProperty(kWindowVisibilityAnimationDurationKey); - if (duration == 0 && window->type() == aura::client::WINDOW_TYPE_MENU) { - return base::TimeDelta::FromMilliseconds( - kDefaultAnimationDurationForMenuMS); - } - return TimeDelta::FromInternalValue(duration); -} - -// Gets/sets the WindowVisibilityAnimationType associated with a window. -// TODO(beng): redundant/fold into method on public api? -int GetWindowVisibilityAnimationType(aura::Window* window) { - int type = window->GetProperty(kWindowVisibilityAnimationTypeKey); - if (type == WINDOW_VISIBILITY_ANIMATION_TYPE_DEFAULT) { - return (window->type() == aura::client::WINDOW_TYPE_MENU || - window->type() == aura::client::WINDOW_TYPE_TOOLTIP) ? - WINDOW_VISIBILITY_ANIMATION_TYPE_FADE : - WINDOW_VISIBILITY_ANIMATION_TYPE_DROP; - } - return type; -} - -// Observes a hide animation. -// A window can be hidden for a variety of reasons. Sometimes, Hide() will be -// called and life is simple. Sometimes, the window is actually bound to a -// views::Widget and that Widget is closed, and life is a little more -// complicated. When a Widget is closed the aura::Window* is actually not -// destroyed immediately - it is actually just immediately hidden and then -// destroyed when the stack unwinds. To handle this case, we start the hide -// animation immediately when the window is hidden, then when the window is -// subsequently destroyed this object acquires ownership of the window's layer, -// so that it can continue animating it until the animation completes. -// Regardless of whether or not the window is destroyed, this object deletes -// itself when the animation completes. -class HidingWindowAnimationObserver : public ui::ImplicitAnimationObserver, - public aura::WindowObserver { - public: - explicit HidingWindowAnimationObserver(aura::Window* window) - : window_(window) { - window_->AddObserver(this); - } - virtual ~HidingWindowAnimationObserver() { - STLDeleteElements(&layers_); - } - - private: - // Overridden from ui::ImplicitAnimationObserver: - virtual void OnImplicitAnimationsCompleted() OVERRIDE { - // Window may have been destroyed by this point. - if (window_) { - aura::client::AnimationHost* animation_host = - aura::client::GetAnimationHost(window_); - if (animation_host) - animation_host->OnWindowHidingAnimationCompleted(); - window_->RemoveObserver(this); - } - delete this; - } - - // Overridden from aura::WindowObserver: - virtual void OnWindowDestroying(aura::Window* window) OVERRIDE { - DCHECK_EQ(window, window_); - DCHECK(layers_.empty()); - AcquireAllLayers(window_); - - // If the Widget has views with layers, then it is necessary to take - // ownership of those layers too. - views::Widget* widget = views::Widget::GetWidgetForNativeWindow(window_); - const views::Widget* const_widget = widget; - if (widget && const_widget->GetRootView() && widget->GetContentsView()) - AcquireAllViewLayers(widget->GetContentsView()); - window_->RemoveObserver(this); - window_ = NULL; - } - - void AcquireAllLayers(aura::Window* window) { - ui::Layer* layer = window->AcquireLayer(); - DCHECK(layer); - layers_.push_back(layer); - for (aura::Window::Windows::const_iterator it = window->children().begin(); - it != window->children().end(); - ++it) - AcquireAllLayers(*it); - } - - void AcquireAllViewLayers(views::View* view) { - for (int i = 0; i < view->child_count(); ++i) - AcquireAllViewLayers(view->child_at(i)); - if (view->layer()) { - ui::Layer* layer = view->RecreateLayer(); - if (layer) { - layer->SuppressPaint(); - layers_.push_back(layer); - } - } - } - - aura::Window* window_; - std::vector<ui::Layer*> layers_; - - DISALLOW_COPY_AND_ASSIGN(HidingWindowAnimationObserver); -}; - -void GetTransformRelativeToRoot(ui::Layer* layer, gfx::Transform* transform) { - const Layer* root = layer; - while (root->parent()) - root = root->parent(); - layer->GetTargetTransformRelativeTo(root, transform); -} - -gfx::Rect GetLayerWorldBoundsAfterTransform(ui::Layer* layer, - const gfx::Transform& transform) { - gfx::Transform in_world = transform; - GetTransformRelativeToRoot(layer, &in_world); - - gfx::RectF transformed = layer->bounds(); - in_world.TransformRect(&transformed); - - return gfx::ToEnclosingRect(transformed); -} - -// Augment the host window so that the enclosing bounds of the full -// animation will fit inside of it. -void AugmentWindowSize(aura::Window* window, - const gfx::Transform& end_transform) { - aura::client::AnimationHost* animation_host = - aura::client::GetAnimationHost(window); - if (!animation_host) - return; - - const gfx::Rect& world_at_start = window->bounds(); - gfx::Rect world_at_end = - GetLayerWorldBoundsAfterTransform(window->layer(), end_transform); - gfx::Rect union_in_window_space = - gfx::UnionRects(world_at_start, world_at_end); - - // Calculate the top left and bottom right deltas to be added to the window - // bounds. - gfx::Vector2d top_left_delta(world_at_start.x() - union_in_window_space.x(), - world_at_start.y() - union_in_window_space.y()); - - gfx::Vector2d bottom_right_delta( - union_in_window_space.x() + union_in_window_space.width() - - (world_at_start.x() + world_at_start.width()), - union_in_window_space.y() + union_in_window_space.height() - - (world_at_start.y() + world_at_start.height())); - - DCHECK(top_left_delta.x() >= 0 && top_left_delta.y() >= 0 && - bottom_right_delta.x() >= 0 && bottom_right_delta.y() >= 0); - - animation_host->SetHostTransitionOffsets(top_left_delta, bottom_right_delta); -} - -// Shows a window using an animation, animating its opacity from 0.f to 1.f, -// its visibility to true, and its transform from |start_transform| to -// |end_transform|. -void AnimateShowWindowCommon(aura::Window* window, - const gfx::Transform& start_transform, - const gfx::Transform& end_transform) { - window->layer()->set_delegate(window); - - AugmentWindowSize(window, end_transform); - - window->layer()->SetOpacity(kWindowAnimation_HideOpacity); - window->layer()->SetTransform(start_transform); - window->layer()->SetVisible(true); - - { - // Property sets within this scope will be implicitly animated. - ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator()); - base::TimeDelta duration = GetWindowVisibilityAnimationDuration(window); - if (duration.ToInternalValue() > 0) - settings.SetTransitionDuration(duration); - - window->layer()->SetTransform(end_transform); - window->layer()->SetOpacity(kWindowAnimation_ShowOpacity); - } -} - -// Hides a window using an animation, animating its opacity from 1.f to 0.f, -// its visibility to false, and its transform to |end_transform|. -void AnimateHideWindowCommon(aura::Window* window, - const gfx::Transform& end_transform) { - AugmentWindowSize(window, end_transform); - window->layer()->set_delegate(NULL); - - // Property sets within this scope will be implicitly animated. - ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator()); - settings.AddObserver(new HidingWindowAnimationObserver(window)); - - base::TimeDelta duration = GetWindowVisibilityAnimationDuration(window); - if (duration.ToInternalValue() > 0) - settings.SetTransitionDuration(duration); - - window->layer()->SetOpacity(kWindowAnimation_HideOpacity); - window->layer()->SetTransform(end_transform); - window->layer()->SetVisible(false); -} - -static gfx::Transform GetScaleForWindow(aura::Window* window) { - gfx::Rect bounds = window->bounds(); - gfx::Transform scale = gfx::GetScaleTransform( - gfx::Point(kWindowAnimation_TranslateFactor * bounds.width(), - kWindowAnimation_TranslateFactor * bounds.height()), - kWindowAnimation_ScaleFactor); - return scale; -} - -// Show/Hide windows using a shrink animation. -void AnimateShowWindow_Drop(aura::Window* window) { - AnimateShowWindowCommon(window, GetScaleForWindow(window), gfx::Transform()); -} - -void AnimateHideWindow_Drop(aura::Window* window) { - AnimateHideWindowCommon(window, GetScaleForWindow(window)); -} - -// Show/Hide windows using a vertical Glenimation. -void AnimateShowWindow_Vertical(aura::Window* window) { - gfx::Transform transform; - transform.Translate(0, window->GetProperty( - kWindowVisibilityAnimationVerticalPositionKey)); - AnimateShowWindowCommon(window, transform, gfx::Transform()); -} - -void AnimateHideWindow_Vertical(aura::Window* window) { - gfx::Transform transform; - transform.Translate(0, window->GetProperty( - kWindowVisibilityAnimationVerticalPositionKey)); - AnimateHideWindowCommon(window, transform); -} - -// Show/Hide windows using a fade. -void AnimateShowWindow_Fade(aura::Window* window) { - AnimateShowWindowCommon(window, gfx::Transform(), gfx::Transform()); -} - -void AnimateHideWindow_Fade(aura::Window* window) { - AnimateHideWindowCommon(window, gfx::Transform()); -} - -ui::LayerAnimationElement* CreateGrowShrinkElement( - aura::Window* window, bool grow) { - scoped_ptr<ui::InterpolatedTransform> scale(new ui::InterpolatedScale( - gfx::Point3F(kWindowAnimation_Bounce_Scale, - kWindowAnimation_Bounce_Scale, - 1), - gfx::Point3F(1, 1, 1))); - scoped_ptr<ui::InterpolatedTransform> scale_about_pivot( - new ui::InterpolatedTransformAboutPivot( - gfx::Point(window->bounds().width() * 0.5, - window->bounds().height() * 0.5), - scale.release())); - scale_about_pivot->SetReversed(grow); - scoped_ptr<ui::LayerAnimationElement> transition( - ui::LayerAnimationElement::CreateInterpolatedTransformElement( - scale_about_pivot.release(), - base::TimeDelta::FromMilliseconds( - kWindowAnimation_Bounce_DurationMS * - kWindowAnimation_Bounce_GrowShrinkDurationPercent / 100))); - transition->set_tween_type(grow ? gfx::Tween::EASE_OUT : gfx::Tween::EASE_IN); - return transition.release(); -} - -void AnimateBounce(aura::Window* window) { - ui::ScopedLayerAnimationSettings scoped_settings( - window->layer()->GetAnimator()); - scoped_settings.SetPreemptionStrategy( - ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); - window->layer()->set_delegate(window); - scoped_ptr<ui::LayerAnimationSequence> sequence( - new ui::LayerAnimationSequence); - sequence->AddElement(CreateGrowShrinkElement(window, true)); - ui::LayerAnimationElement::AnimatableProperties paused_properties; - paused_properties.insert(ui::LayerAnimationElement::BOUNDS); - sequence->AddElement(ui::LayerAnimationElement::CreatePauseElement( - paused_properties, - base::TimeDelta::FromMilliseconds( - kWindowAnimation_Bounce_DurationMS * - (100 - 2 * kWindowAnimation_Bounce_GrowShrinkDurationPercent) / - 100))); - sequence->AddElement(CreateGrowShrinkElement(window, false)); - window->layer()->GetAnimator()->StartAnimation(sequence.release()); -} - -void AddLayerAnimationsForRotate(aura::Window* window, bool show) { - window->layer()->set_delegate(window); - if (show) - window->layer()->SetOpacity(kWindowAnimation_HideOpacity); - - base::TimeDelta duration = base::TimeDelta::FromMilliseconds( - kWindowAnimation_Rotate_DurationMS); - - if (!show) { - new HidingWindowAnimationObserver(window); - window->layer()->GetAnimator()->SchedulePauseForProperties( - duration * (100 - kWindowAnimation_Rotate_OpacityDurationPercent) / 100, - ui::LayerAnimationElement::OPACITY, - -1); - } - scoped_ptr<ui::LayerAnimationElement> opacity( - ui::LayerAnimationElement::CreateOpacityElement( - show ? kWindowAnimation_ShowOpacity : kWindowAnimation_HideOpacity, - duration * kWindowAnimation_Rotate_OpacityDurationPercent / 100)); - opacity->set_tween_type(gfx::Tween::EASE_IN_OUT); - window->layer()->GetAnimator()->ScheduleAnimation( - new ui::LayerAnimationSequence(opacity.release())); - - float xcenter = window->bounds().width() * 0.5; - - gfx::Transform transform; - transform.Translate(xcenter, 0); - transform.ApplyPerspectiveDepth(kWindowAnimation_Rotate_PerspectiveDepth); - transform.Translate(-xcenter, 0); - scoped_ptr<ui::InterpolatedTransform> perspective( - new ui::InterpolatedConstantTransform(transform)); - - scoped_ptr<ui::InterpolatedTransform> scale( - new ui::InterpolatedScale(1, kWindowAnimation_Rotate_ScaleFactor)); - scoped_ptr<ui::InterpolatedTransform> scale_about_pivot( - new ui::InterpolatedTransformAboutPivot( - gfx::Point(xcenter, kWindowAnimation_Rotate_TranslateY), - scale.release())); - - scoped_ptr<ui::InterpolatedTransform> translation( - new ui::InterpolatedTranslation(gfx::Point(), gfx::Point( - 0, kWindowAnimation_Rotate_TranslateY))); - - scoped_ptr<ui::InterpolatedTransform> rotation( - new ui::InterpolatedAxisAngleRotation( - gfx::Vector3dF(1, 0, 0), 0, kWindowAnimation_Rotate_DegreesX)); - - scale_about_pivot->SetChild(perspective.release()); - translation->SetChild(scale_about_pivot.release()); - rotation->SetChild(translation.release()); - rotation->SetReversed(show); - - scoped_ptr<ui::LayerAnimationElement> transition( - ui::LayerAnimationElement::CreateInterpolatedTransformElement( - rotation.release(), duration)); - - window->layer()->GetAnimator()->ScheduleAnimation( - new ui::LayerAnimationSequence(transition.release())); -} - -void AnimateShowWindow_Rotate(aura::Window* window) { - AddLayerAnimationsForRotate(window, true); -} - -void AnimateHideWindow_Rotate(aura::Window* window) { - AddLayerAnimationsForRotate(window, false); -} - -bool AnimateShowWindow(aura::Window* window) { - if (!HasWindowVisibilityAnimationTransition(window, ANIMATE_SHOW)) { - if (HasWindowVisibilityAnimationTransition(window, ANIMATE_HIDE)) { - // Since hide animation may have changed opacity and transform, - // reset them to show the window. - window->layer()->set_delegate(window); - window->layer()->SetOpacity(kWindowAnimation_ShowOpacity); - window->layer()->SetTransform(gfx::Transform()); - } - return false; - } - - switch (GetWindowVisibilityAnimationType(window)) { - case WINDOW_VISIBILITY_ANIMATION_TYPE_DROP: - AnimateShowWindow_Drop(window); - return true; - case WINDOW_VISIBILITY_ANIMATION_TYPE_VERTICAL: - AnimateShowWindow_Vertical(window); - return true; - case WINDOW_VISIBILITY_ANIMATION_TYPE_FADE: - AnimateShowWindow_Fade(window); - return true; - case WINDOW_VISIBILITY_ANIMATION_TYPE_ROTATE: - AnimateShowWindow_Rotate(window); - return true; - default: - return false; - } -} - -bool AnimateHideWindow(aura::Window* window) { - if (!HasWindowVisibilityAnimationTransition(window, ANIMATE_HIDE)) { - if (HasWindowVisibilityAnimationTransition(window, ANIMATE_SHOW)) { - // Since show animation may have changed opacity and transform, - // reset them, though the change should be hidden. - window->layer()->set_delegate(NULL); - window->layer()->SetOpacity(kWindowAnimation_HideOpacity); - window->layer()->SetTransform(gfx::Transform()); - } - return false; - } - - switch (GetWindowVisibilityAnimationType(window)) { - case WINDOW_VISIBILITY_ANIMATION_TYPE_DROP: - AnimateHideWindow_Drop(window); - return true; - case WINDOW_VISIBILITY_ANIMATION_TYPE_VERTICAL: - AnimateHideWindow_Vertical(window); - return true; - case WINDOW_VISIBILITY_ANIMATION_TYPE_FADE: - AnimateHideWindow_Fade(window); - return true; - case WINDOW_VISIBILITY_ANIMATION_TYPE_ROTATE: - AnimateHideWindow_Rotate(window); - return true; - default: - return false; - } -} - -} // namespace - -//////////////////////////////////////////////////////////////////////////////// -// External interface - -void SetWindowVisibilityAnimationType(aura::Window* window, int type) { - window->SetProperty(kWindowVisibilityAnimationTypeKey, type); -} - -int GetWindowVisibilityAnimationType(aura::Window* window) { - return window->GetProperty(kWindowVisibilityAnimationTypeKey); -} - -void SetWindowVisibilityAnimationTransition( - aura::Window* window, - WindowVisibilityAnimationTransition transition) { - window->SetProperty(kWindowVisibilityAnimationTransitionKey, transition); -} - -bool HasWindowVisibilityAnimationTransition( - aura::Window* window, - WindowVisibilityAnimationTransition transition) { - WindowVisibilityAnimationTransition prop = window->GetProperty( - kWindowVisibilityAnimationTransitionKey); - return (prop & transition) != 0; -} - -void SetWindowVisibilityAnimationDuration(aura::Window* window, - const TimeDelta& duration) { - window->SetProperty(kWindowVisibilityAnimationDurationKey, - static_cast<int>(duration.ToInternalValue())); -} - -void SetWindowVisibilityAnimationVerticalPosition(aura::Window* window, - float position) { - window->SetProperty(kWindowVisibilityAnimationVerticalPositionKey, position); -} - -ui::ImplicitAnimationObserver* CreateHidingWindowAnimationObserver( - aura::Window* window) { - return new HidingWindowAnimationObserver(window); -} - -bool AnimateOnChildWindowVisibilityChanged(aura::Window* window, bool visible) { - if (WindowAnimationsDisabled(window)) - return false; - if (visible) - return AnimateShowWindow(window); - // Don't start hiding the window again if it's already being hidden. - return window->layer()->GetTargetOpacity() != 0.0f && - AnimateHideWindow(window); -} - -bool AnimateWindow(aura::Window* window, WindowAnimationType type) { - switch (type) { - case WINDOW_ANIMATION_TYPE_BOUNCE: - AnimateBounce(window); - return true; - default: - NOTREACHED(); - return false; - } -} - -bool WindowAnimationsDisabled(aura::Window* window) { - return (window && - window->GetProperty(aura::client::kAnimationsDisabledKey)) || - CommandLine::ForCurrentProcess()->HasSwitch( - switches::kWindowAnimationsDisabled); -} - -} // namespace corewm -} // namespace views diff --git a/chromium/ui/views/corewm/window_animations.h b/chromium/ui/views/corewm/window_animations.h deleted file mode 100644 index 996c215dc89..00000000000 --- a/chromium/ui/views/corewm/window_animations.h +++ /dev/null @@ -1,101 +0,0 @@ -// 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. - -#ifndef UI_VIEWS_COREWM_WINDOW_ANIMATIONS_H_ -#define UI_VIEWS_COREWM_WINDOW_ANIMATIONS_H_ - -#include <vector> - -#include "ui/views/views_export.h" - -namespace aura { -class Window; -} -namespace base { -class TimeDelta; -} -namespace gfx { -class Rect; -} -namespace ui { -class ImplicitAnimationObserver; -class Layer; -class LayerAnimationSequence; -} - -namespace views { -namespace corewm { - -// A variety of canned animations for window transitions. -enum WindowVisibilityAnimationType { - WINDOW_VISIBILITY_ANIMATION_TYPE_DEFAULT = 0, // Default. Lets the system - // decide based on window - // type. - WINDOW_VISIBILITY_ANIMATION_TYPE_DROP, // Window shrinks in. - WINDOW_VISIBILITY_ANIMATION_TYPE_VERTICAL, // Vertical Glenimation. - WINDOW_VISIBILITY_ANIMATION_TYPE_FADE, // Fades in/out. - WINDOW_VISIBILITY_ANIMATION_TYPE_ROTATE, // Window rotates in. - - // Downstream library animations start above this point. - WINDOW_VISIBILITY_ANIMATION_MAX -}; - -// Canned animations that take effect once but don't have a symmetric pair as -// visibility animations do. -enum WindowAnimationType { - WINDOW_ANIMATION_TYPE_BOUNCE = 0, // Window scales up and down. -}; - -// Type of visibility change transition that a window should animate. -// Default behavior is to animate both show and hide. -enum WindowVisibilityAnimationTransition { - ANIMATE_SHOW = 0x1, - ANIMATE_HIDE = 0x2, - ANIMATE_BOTH = ANIMATE_SHOW | ANIMATE_HIDE, - ANIMATE_NONE = 0x4, -}; - -// These two methods use int for type rather than WindowVisibilityAnimationType -// since downstream libraries can extend the set of animations. -VIEWS_EXPORT void SetWindowVisibilityAnimationType(aura::Window* window, - int type); -VIEWS_EXPORT int GetWindowVisibilityAnimationType(aura::Window* window); - -VIEWS_EXPORT void SetWindowVisibilityAnimationTransition( - aura::Window* window, - WindowVisibilityAnimationTransition transition); - -VIEWS_EXPORT bool HasWindowVisibilityAnimationTransition( - aura::Window* window, - WindowVisibilityAnimationTransition transition); - -VIEWS_EXPORT void SetWindowVisibilityAnimationDuration( - aura::Window* window, - const base::TimeDelta& duration); - -VIEWS_EXPORT void SetWindowVisibilityAnimationVerticalPosition( - aura::Window* window, - float position); - -// Creates an ImplicitAnimationObserver that takes ownership of the layers -// associated with a Window so that the animation can continue after the Window -// has been destroyed. -// The returned object deletes itself when the animations are done. -VIEWS_EXPORT ui::ImplicitAnimationObserver* CreateHidingWindowAnimationObserver( - aura::Window* window); - -// Returns false if the |window| didn't animate. -VIEWS_EXPORT bool AnimateOnChildWindowVisibilityChanged(aura::Window* window, - bool visible); -VIEWS_EXPORT bool AnimateWindow(aura::Window* window, WindowAnimationType type); - -// Returns true if window animations are disabled for |window|. Window -// animations are enabled by default. If |window| is NULL, this just checks -// if the global flag disabling window animations is present. -VIEWS_EXPORT bool WindowAnimationsDisabled(aura::Window* window); - -} // namespace corewm -} // namespace views - -#endif // UI_VIEWS_COREWM_WINDOW_ANIMATIONS_H_ diff --git a/chromium/ui/views/corewm/window_animations_unittest.cc b/chromium/ui/views/corewm/window_animations_unittest.cc deleted file mode 100644 index 89d48c6ce8d..00000000000 --- a/chromium/ui/views/corewm/window_animations_unittest.cc +++ /dev/null @@ -1,143 +0,0 @@ -// 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. - -#include "ui/views/corewm/window_animations.h" - -#include "base/time/time.h" -#include "ui/aura/client/animation_host.h" -#include "ui/aura/test/aura_test_base.h" -#include "ui/aura/test/test_windows.h" -#include "ui/aura/window.h" -#include "ui/compositor/layer.h" -#include "ui/compositor/layer_animator.h" -#include "ui/compositor/scoped_animation_duration_scale_mode.h" -#include "ui/gfx/animation/animation_container_element.h" -#include "ui/gfx/vector2d.h" - -using aura::Window; -using ui::Layer; - -namespace views { -namespace corewm { - -class WindowAnimationsTest : public aura::test::AuraTestBase { - public: - WindowAnimationsTest() {} - - virtual void TearDown() OVERRIDE { - AuraTestBase::TearDown(); - } - - private: - DISALLOW_COPY_AND_ASSIGN(WindowAnimationsTest); -}; - -TEST_F(WindowAnimationsTest, LayerTargetVisibility) { - scoped_ptr<aura::Window> window( - aura::test::CreateTestWindowWithId(0, NULL)); - - // Layer target visibility changes according to Show/Hide. - window->Show(); - EXPECT_TRUE(window->layer()->GetTargetVisibility()); - window->Hide(); - EXPECT_FALSE(window->layer()->GetTargetVisibility()); - window->Show(); - EXPECT_TRUE(window->layer()->GetTargetVisibility()); -} - -TEST_F(WindowAnimationsTest, LayerTargetVisibility_AnimateShow) { - // Tests if opacity and transform are reset when only show animation is - // enabled. See also LayerTargetVisibility_AnimateHide. - // Since the window is not visible after Hide() is called, opacity and - // transform shouldn't matter in case of ANIMATE_SHOW, but we reset them - // to keep consistency. - - scoped_ptr<aura::Window> window(aura::test::CreateTestWindowWithId(0, NULL)); - SetWindowVisibilityAnimationTransition(window.get(), ANIMATE_SHOW); - - // Layer target visibility and opacity change according to Show/Hide. - window->Show(); - AnimateOnChildWindowVisibilityChanged(window.get(), true); - EXPECT_TRUE(window->layer()->GetTargetVisibility()); - EXPECT_EQ(1, window->layer()->opacity()); - - window->Hide(); - AnimateOnChildWindowVisibilityChanged(window.get(), false); - EXPECT_FALSE(window->layer()->GetTargetVisibility()); - EXPECT_EQ(0, window->layer()->opacity()); - EXPECT_EQ(gfx::Transform(), window->layer()->transform()); - - window->Show(); - AnimateOnChildWindowVisibilityChanged(window.get(), true); - EXPECT_TRUE(window->layer()->GetTargetVisibility()); - EXPECT_EQ(1, window->layer()->opacity()); -} - -TEST_F(WindowAnimationsTest, LayerTargetVisibility_AnimateHide) { - // Tests if opacity and transform are reset when only hide animation is - // enabled. Hide animation changes opacity and transform in addition to - // visibility, so we need to reset not only visibility but also opacity - // and transform to show the window. - - scoped_ptr<aura::Window> window(aura::test::CreateTestWindowWithId(0, NULL)); - SetWindowVisibilityAnimationTransition(window.get(), ANIMATE_HIDE); - - // Layer target visibility and opacity change according to Show/Hide. - window->Show(); - AnimateOnChildWindowVisibilityChanged(window.get(), true); - EXPECT_TRUE(window->layer()->GetTargetVisibility()); - EXPECT_EQ(1, window->layer()->opacity()); - EXPECT_EQ(gfx::Transform(), window->layer()->transform()); - - window->Hide(); - AnimateOnChildWindowVisibilityChanged(window.get(), false); - EXPECT_FALSE(window->layer()->GetTargetVisibility()); - EXPECT_EQ(0, window->layer()->opacity()); - - window->Show(); - AnimateOnChildWindowVisibilityChanged(window.get(), true); - EXPECT_TRUE(window->layer()->GetTargetVisibility()); - EXPECT_EQ(1, window->layer()->opacity()); - EXPECT_EQ(gfx::Transform(), window->layer()->transform()); -} - -// A simple AnimationHost implementation for the NotifyHideCompleted test. -class NotifyHideCompletedAnimationHost : public aura::client::AnimationHost { - public: - NotifyHideCompletedAnimationHost() : hide_completed_(false) {} - virtual ~NotifyHideCompletedAnimationHost() {} - - // Overridden from TestWindowDelegate: - virtual void OnWindowHidingAnimationCompleted() OVERRIDE { - hide_completed_ = true; - } - - virtual void SetHostTransitionOffsets( - const gfx::Vector2d& top_left, - const gfx::Vector2d& bottom_right) OVERRIDE {} - - bool hide_completed() const { return hide_completed_; } - - private: - bool hide_completed_; - - DISALLOW_COPY_AND_ASSIGN(NotifyHideCompletedAnimationHost); -}; - -TEST_F(WindowAnimationsTest, NotifyHideCompleted) { - NotifyHideCompletedAnimationHost animation_host; - scoped_ptr<aura::Window> window(aura::test::CreateTestWindowWithId(0, NULL)); - aura::client::SetAnimationHost(window.get(), &animation_host); - views::corewm::SetWindowVisibilityAnimationType( - window.get(), WINDOW_VISIBILITY_ANIMATION_TYPE_FADE); - AnimateOnChildWindowVisibilityChanged(window.get(), true); - EXPECT_TRUE(window->layer()->visible()); - - EXPECT_FALSE(animation_host.hide_completed()); - AnimateOnChildWindowVisibilityChanged(window.get(), false); - EXPECT_TRUE(animation_host.hide_completed()); -} - -} // namespace corewm -} // namespace views diff --git a/chromium/ui/views/corewm/window_modality_controller.cc b/chromium/ui/views/corewm/window_modality_controller.cc deleted file mode 100644 index b52a9d6ad8c..00000000000 --- a/chromium/ui/views/corewm/window_modality_controller.cc +++ /dev/null @@ -1,196 +0,0 @@ -// 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. - -#include "ui/views/corewm/window_modality_controller.h" - -#include <algorithm> - -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/client/capture_client.h" -#include "ui/aura/env.h" -#include "ui/aura/root_window.h" -#include "ui/aura/window.h" -#include "ui/aura/window_property.h" -#include "ui/base/ui_base_types.h" -#include "ui/events/event.h" -#include "ui/events/event_target.h" -#include "ui/events/gestures/gesture_recognizer.h" -#include "ui/views/corewm/window_animations.h" -#include "ui/views/corewm/window_util.h" - -namespace views { -namespace corewm { - -// Transient child's modal parent. -extern const aura::WindowProperty<aura::Window*>* const kModalParentKey; -DEFINE_WINDOW_PROPERTY_KEY(aura::Window*, kModalParentKey, NULL); - -namespace { - -bool HasAncestor(aura::Window* window, aura::Window* ancestor) { - if (!window) - return false; - if (window == ancestor) - return true; - return HasAncestor(window->parent(), ancestor); -} - -bool TransientChildIsWindowModal(aura::Window* window) { - return window->GetProperty(aura::client::kModalKey) == ui::MODAL_TYPE_WINDOW; -} - -bool TransientChildIsSystemModal(aura::Window* window) { - return window->GetProperty(aura::client::kModalKey) == ui::MODAL_TYPE_SYSTEM; -} - -bool TransientChildIsChildModal(aura::Window* window) { - return window->GetProperty(aura::client::kModalKey) == ui::MODAL_TYPE_CHILD; -} - -aura::Window* GetModalParent(aura::Window* window) { - return window->GetProperty(kModalParentKey); -} - -bool IsModalTransientChild(aura::Window* transient, aura::Window* original) { - return transient->IsVisible() && - (TransientChildIsWindowModal(transient) || - TransientChildIsSystemModal(transient) || - (TransientChildIsChildModal(transient) && - (HasAncestor(original, GetModalParent(transient))))); -} - -aura::Window* GetModalTransientChild( - aura::Window* activatable, - aura::Window* original) { - aura::Window::Windows::const_iterator it; - for (it = activatable->transient_children().begin(); - it != activatable->transient_children().end(); - ++it) { - aura::Window* transient = *it; - if (IsModalTransientChild(transient, original)) { - return transient->transient_children().empty() ? - transient : GetModalTransientChild(transient, original); - } - } - return NULL; -} - -} // namespace - -void SetModalParent(aura::Window* child, aura::Window* parent) { - child->SetProperty(kModalParentKey, parent); -} - -aura::Window* GetModalTransient(aura::Window* window) { - if (!window) - return NULL; - - // We always want to check the for the transient child of the toplevel window. - aura::Window* toplevel = GetToplevelWindow(window); - if (!toplevel) - return NULL; - - return GetModalTransientChild(toplevel, window); -} - -//////////////////////////////////////////////////////////////////////////////// -// WindowModalityController, public: - -WindowModalityController::WindowModalityController( - ui::EventTarget* event_target) - : event_target_(event_target) { - aura::Env::GetInstance()->AddObserver(this); - DCHECK(event_target->IsPreTargetListEmpty()); - event_target_->AddPreTargetHandler(this); -} - -WindowModalityController::~WindowModalityController() { - event_target_->RemovePreTargetHandler(this); - aura::Env::GetInstance()->RemoveObserver(this); - for (size_t i = 0; i < windows_.size(); ++i) - windows_[i]->RemoveObserver(this); -} - -//////////////////////////////////////////////////////////////////////////////// -// WindowModalityController, aura::EventFilter implementation: - -void WindowModalityController::OnKeyEvent(ui::KeyEvent* event) { - aura::Window* target = static_cast<aura::Window*>(event->target()); - if (GetModalTransient(target)) - event->SetHandled(); -} - -void WindowModalityController::OnMouseEvent(ui::MouseEvent* event) { - aura::Window* target = static_cast<aura::Window*>(event->target()); - if (ProcessLocatedEvent(target, event)) - event->SetHandled(); -} - -void WindowModalityController::OnTouchEvent(ui::TouchEvent* event) { - aura::Window* target = static_cast<aura::Window*>(event->target()); - if (ProcessLocatedEvent(target, event)) - event->SetHandled(); -} - -//////////////////////////////////////////////////////////////////////////////// -// WindowModalityController, aura::EnvObserver implementation: - -void WindowModalityController::OnWindowInitialized(aura::Window* window) { - windows_.push_back(window); - window->AddObserver(this); -} - -//////////////////////////////////////////////////////////////////////////////// -// WindowModalityController, aura::WindowObserver implementation: - -void WindowModalityController::OnWindowPropertyChanged(aura::Window* window, - const void* key, - intptr_t old) { - // In tests, we sometimes create the modality relationship after a window is - // visible. - if (key == aura::client::kModalKey && - window->GetProperty(aura::client::kModalKey) != ui::MODAL_TYPE_NONE && - window->IsVisible()) { - ActivateWindow(window); - ui::GestureRecognizer::Get()->TransferEventsTo( - window->transient_parent(), NULL); - } -} - -void WindowModalityController::OnWindowVisibilityChanged( - aura::Window* window, - bool visible) { - if (visible && window->GetProperty(aura::client::kModalKey) != - ui::MODAL_TYPE_NONE) { - ui::GestureRecognizer::Get()->TransferEventsTo( - window->transient_parent(), NULL); - // Make sure no other window has capture, otherwise |window| won't get mouse - // events. - aura::Window* capture_window = aura::client::GetCaptureWindow(window); - if (capture_window) - capture_window->ReleaseCapture(); - } -} - -void WindowModalityController::OnWindowDestroyed(aura::Window* window) { - windows_.erase(std::find(windows_.begin(), windows_.end(), window)); - window->RemoveObserver(this); -} - -bool WindowModalityController::ProcessLocatedEvent(aura::Window* target, - ui::LocatedEvent* event) { - if (event->handled()) - return false; - aura::Window* modal_transient_child = GetModalTransient(target); - if (modal_transient_child && (event->type() == ui::ET_MOUSE_PRESSED || - event->type() == ui::ET_TOUCH_PRESSED)) { - AnimateWindow(modal_transient_child, WINDOW_ANIMATION_TYPE_BOUNCE); - } - if (event->type() == ui::ET_TOUCH_CANCELLED) - return false; - return !!modal_transient_child; -} - -} // namespace corewm -} // namespace views diff --git a/chromium/ui/views/corewm/window_modality_controller.h b/chromium/ui/views/corewm/window_modality_controller.h deleted file mode 100644 index 88150a54253..00000000000 --- a/chromium/ui/views/corewm/window_modality_controller.h +++ /dev/null @@ -1,73 +0,0 @@ -// 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. - -#ifndef UI_VIEWS_COREWM_WINDOW_MODALITY_CONTROLLER_H_ -#define UI_VIEWS_COREWM_WINDOW_MODALITY_CONTROLLER_H_ - -#include <vector> - -#include "base/compiler_specific.h" -#include "ui/aura/env_observer.h" -#include "ui/aura/window_observer.h" -#include "ui/events/event_handler.h" -#include "ui/views/views_export.h" - -namespace ui { -class EventTarget; -class LocatedEvent; -} - -namespace views { -namespace corewm { - -// Sets the modal parent for the child. -VIEWS_EXPORT void SetModalParent(aura::Window* child, aura::Window* parent); - -// Returns the modal transient child of |window|, or NULL if |window| does not -// have any modal transient children. -VIEWS_EXPORT aura::Window* GetModalTransient(aura::Window* window); - -// WindowModalityController is an event filter that consumes events sent to -// windows that are the transient parents of window-modal windows. This filter -// must be added to the CompoundEventFilter so that activation works properly. -class VIEWS_EXPORT WindowModalityController : public ui::EventHandler, - public aura::EnvObserver, - public aura::WindowObserver { - public: - explicit WindowModalityController(ui::EventTarget* event_target); - virtual ~WindowModalityController(); - - // Overridden from ui::EventHandler: - virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE; - virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE; - virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE; - - // Overridden from aura::EnvObserver: - virtual void OnWindowInitialized(aura::Window* window) OVERRIDE; - - // Overridden from aura::WindowObserver: - virtual void OnWindowPropertyChanged(aura::Window* window, - const void* key, - intptr_t old) OVERRIDE; - virtual void OnWindowVisibilityChanged(aura::Window* window, - bool visible) OVERRIDE; - virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE; - - private: - // Processes a mouse/touch event, and returns true if the event should be - // consumed. - bool ProcessLocatedEvent(aura::Window* target, - ui::LocatedEvent* event); - - std::vector<aura::Window*> windows_; - - ui::EventTarget* event_target_; - - DISALLOW_COPY_AND_ASSIGN(WindowModalityController); -}; - -} // namespace corewm -} // namespace views - -#endif // UI_VIEWS_COREWM_WINDOW_MODALITY_CONTROLLER_H_ diff --git a/chromium/ui/views/corewm/window_util.cc b/chromium/ui/views/corewm/window_util.cc deleted file mode 100644 index eaee174d738..00000000000 --- a/chromium/ui/views/corewm/window_util.cc +++ /dev/null @@ -1,141 +0,0 @@ -// 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. - -#include "ui/views/corewm/window_util.h" - -#include "ui/aura/client/activation_client.h" -#include "ui/aura/root_window.h" -#include "ui/aura/window.h" -#include "ui/compositor/layer.h" -#include "ui/views/view.h" -#include "ui/views/widget/widget.h" - -namespace { - -// Helper method for RecreateWindowLayers() which adds all the existing layers -// for |view| and its descendants to |parent_layer|. New layers are created for -// |view| (if it previously had a layer) and any descendants which previously -// had layers. The new layers are blank, so nothing has been painted to them -// yet. Returns true if this method added at least one layer to |parent_layer|. -bool RecreateViewLayers(ui::Layer* parent_layer, views::View* view) { - bool recreated_layer = false; - if (view->layer()) { - ui::Layer* layer = view->RecreateLayer(); - if (layer) { - layer->SuppressPaint(); - parent_layer->Add(layer); - parent_layer = layer; - recreated_layer = true; - } - } - for (int i = 0; i < view->child_count(); ++i) - recreated_layer |= RecreateViewLayers(parent_layer, view->child_at(i)); - - return recreated_layer; -} - -} // namespace - -namespace views { -namespace corewm { - -void ActivateWindow(aura::Window* window) { - DCHECK(window); - DCHECK(window->GetRootWindow()); - aura::client::GetActivationClient(window->GetRootWindow())->ActivateWindow( - window); -} - -void DeactivateWindow(aura::Window* window) { - DCHECK(window); - DCHECK(window->GetRootWindow()); - aura::client::GetActivationClient(window->GetRootWindow())->DeactivateWindow( - window); -} - -bool IsActiveWindow(aura::Window* window) { - DCHECK(window); - if (!window->GetRootWindow()) - return false; - aura::client::ActivationClient* client = - aura::client::GetActivationClient(window->GetRootWindow()); - return client && client->GetActiveWindow() == window; -} - -bool CanActivateWindow(aura::Window* window) { - DCHECK(window); - if (!window->GetRootWindow()) - return false; - aura::client::ActivationClient* client = - aura::client::GetActivationClient(window->GetRootWindow()); - return client && client->CanActivateWindow(window); -} - -aura::Window* GetActivatableWindow(aura::Window* window) { - aura::client::ActivationClient* client = - aura::client::GetActivationClient(window->GetRootWindow()); - return client ? client->GetActivatableWindow(window) : NULL; -} - -aura::Window* GetToplevelWindow(aura::Window* window) { - aura::client::ActivationClient* client = - aura::client::GetActivationClient(window->GetRootWindow()); - return client ? client->GetToplevelWindow(window) : NULL; -} - -void DeepDeleteLayers(ui::Layer* layer) { - std::vector<ui::Layer*> children = layer->children(); - for (std::vector<ui::Layer*>::const_iterator it = children.begin(); - it != children.end(); - ++it) { - ui::Layer* child = *it; - DeepDeleteLayers(child); - } - delete layer; -} - -ui::Layer* RecreateWindowLayers(aura::Window* window, bool set_bounds) { - const gfx::Rect bounds = window->bounds(); - ui::Layer* old_layer = window->RecreateLayer(); - DCHECK(old_layer); - - // Cache the order of |window|'s child layers. If |window| belongs to a widget - // and the widget has both child windows and child views with layers, - // |initial_layer_order| is used to determine the relative order. - std::vector<ui::Layer*> initial_layer_order = window->layer()->children(); - - // Recreate the layers for any child windows of |window|. - for (aura::Window::Windows::const_iterator it = window->children().begin(); - it != window->children().end(); - ++it) { - old_layer->Add(RecreateWindowLayers(*it, set_bounds)); - } - - // Recreate the layers for any child views of |widget|. - bool has_view_layers = false; - views::Widget* widget = views::Widget::GetWidgetForNativeView(window); - if (widget && widget->GetRootView()) - has_view_layers = RecreateViewLayers(old_layer, widget->GetRootView()); - - if (has_view_layers && !window->children().empty()) { - // RecreateViewLayers() added the view layers above the window layers in - // z-order. The window layers and the view layers may have been originally - // intermingled. Reorder |old_layer|'s children based on the initial - // order. - for (size_t i = 0; i < initial_layer_order.size(); ++i) { - ui::Layer* layer = initial_layer_order[i]; - std::vector<ui::Layer*>::const_iterator it = std::find( - old_layer->children().begin(), old_layer->children().end(), layer); - if (it != old_layer->children().end()) - old_layer->StackAtTop(layer); - } - } - - if (set_bounds) - window->SetBounds(bounds); - return old_layer; -} - -} // namespace corewm -} // namespace views diff --git a/chromium/ui/views/corewm/window_util.h b/chromium/ui/views/corewm/window_util.h deleted file mode 100644 index 01a3ea43f06..00000000000 --- a/chromium/ui/views/corewm/window_util.h +++ /dev/null @@ -1,53 +0,0 @@ -// 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. - -#ifndef UI_VIEWS_COREWM_WINDOW_UTIL_H_ -#define UI_VIEWS_COREWM_WINDOW_UTIL_H_ - -#include "base/compiler_specific.h" -#include "ui/views/views_export.h" - -namespace aura { -class Window; -} - -namespace ui { -class Layer; -} - -namespace views { -namespace corewm { - -VIEWS_EXPORT void ActivateWindow(aura::Window* window); -VIEWS_EXPORT void DeactivateWindow(aura::Window* window); -VIEWS_EXPORT bool IsActiveWindow(aura::Window* window); -VIEWS_EXPORT bool CanActivateWindow(aura::Window* window); - -// Retrieves the activatable window for |window|. The ActivationClient makes -// this determination. -VIEWS_EXPORT aura::Window* GetActivatableWindow(aura::Window* window); - -// Retrieves the toplevel window for |window|. The ActivationClient makes this -// determination. -VIEWS_EXPORT aura::Window* GetToplevelWindow(aura::Window* window); - -// Deletes |layer| and all its child layers. -VIEWS_EXPORT void DeepDeleteLayers(ui::Layer* layer); - -// Returns the existing Layer for |window| (and all its descendants) and creates -// a new layer for |window| and all its descendants. This is intended for -// animations that want to animate between the existing visuals and a new window -// state. The caller owns the return value. -// -// As a result of this |window| has freshly created layers, meaning the layers -// are all empty (nothing has been painted to them) and are sized to 0x0. Soon -// after this call you need to reset the bounds of the window. Or, you can pass -// true as the second argument to let the function do that. -VIEWS_EXPORT ui::Layer* RecreateWindowLayers(aura::Window* window, - bool set_bounds) WARN_UNUSED_RESULT; - -} // namespace corewm -} // namespace views - -#endif // UI_VIEWS_COREWM_WINDOW_UTIL_H_ diff --git a/chromium/ui/views/corewm/window_util_unittest.cc b/chromium/ui/views/corewm/window_util_unittest.cc deleted file mode 100644 index fdf3a46fa2f..00000000000 --- a/chromium/ui/views/corewm/window_util_unittest.cc +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright 2013 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/views/corewm/window_util.h" - -#include "ui/aura/root_window.h" -#include "ui/aura/test/aura_test_base.h" -#include "ui/aura/window.h" -#include "ui/compositor/test/test_layers.h" -#include "ui/views/view_constants_aura.h" -#include "ui/views/widget/widget.h" - -class WindowUtilTest : public aura::test::AuraTestBase { - public: - WindowUtilTest() { - } - - virtual ~WindowUtilTest() { - } - - // Creates a widget of TYPE_CONTROL. - // The caller takes ownership of the returned widget. - views::Widget* CreateControlWidget( - aura::Window* parent, - const gfx::Rect& bounds) const WARN_UNUSED_RESULT { - views::Widget::InitParams params(views::Widget::InitParams::TYPE_CONTROL); - params.parent = parent; - params.bounds = bounds; - views::Widget* widget = new views::Widget(); - widget->Init(params); - return widget; - } - - // Returns a view with a layer with the passed in |bounds| and |layer_name|. - // The caller takes ownership of the returned view. - views::View* CreateViewWithLayer( - const gfx::Rect& bounds, - const char* layer_name) const WARN_UNUSED_RESULT { - views::View* view = new views::View(); - view->SetBoundsRect(bounds); - view->SetPaintToLayer(true); - view->layer()->set_name(layer_name); - return view; - } - - private: - DISALLOW_COPY_AND_ASSIGN(WindowUtilTest); -}; - -// Test that RecreateWindowLayers() recreates the layers for all child windows -// and all child views and that the z-order of the recreated layers matches that -// of the original layers. -// Test hierarchy: -// w1 -// +-- v1 -// +-- v2 (no layer) -// +-- v3 (no layer) -// +-- v4 -// +-- w2 -// +-- v5 -// +-- v6 -// +-- v7 -TEST_F(WindowUtilTest, RecreateWindowLayers) { - views::Widget* w1 = CreateControlWidget(root_window(), - gfx::Rect(0, 0, 100, 100)); - w1->GetNativeView()->layer()->set_name("w1"); - - views::View* v2 = new views::View(); - v2->SetBounds(0, 1, 100, 101); - views::View* v3 = new views::View(); - v3->SetBounds(0, 2, 100, 102); - views::View* w2_host_view = new views::View(); - - w1->GetRootView()->AddChildView(CreateViewWithLayer( - gfx::Rect(0, 3, 100, 103), "v1")); - w1->GetRootView()->AddChildView(v2); - v2->AddChildView(v3); - v2->AddChildView(CreateViewWithLayer(gfx::Rect(0, 4, 100, 104), "v4")); - - w1->GetRootView()->AddChildView(w2_host_view); - w1->GetRootView()->AddChildView(CreateViewWithLayer( - gfx::Rect(0, 4, 100, 104), "v7")); - - views::Widget* w2 = CreateControlWidget(w1->GetNativeView(), - gfx::Rect(0, 5, 100, 105)); - w2->GetNativeView()->layer()->set_name("w2"); - w2->GetNativeView()->SetProperty(views::kHostViewKey, w2_host_view); - - views::View* v5 = CreateViewWithLayer(gfx::Rect(0, 6, 100, 106), "v5"); - w2->GetRootView()->AddChildView(v5); - v5->AddChildView(CreateViewWithLayer(gfx::Rect(0, 7, 100, 107), "v6")); - - // Test the initial order of the layers. - ui::Layer* w1_layer = w1->GetNativeView()->layer(); - ASSERT_EQ("w1", w1_layer->name()); - ASSERT_EQ("v1 v4 w2 v7", ui::test::ChildLayerNamesAsString(*w1_layer)); - ui::Layer* w2_layer = w1_layer->children()[2]; - ASSERT_EQ("v5", ui::test::ChildLayerNamesAsString(*w2_layer)); - ui::Layer* v5_layer = w2_layer->children()[0]; - ASSERT_EQ("v6", ui::test::ChildLayerNamesAsString(*v5_layer)); - - w1_layer = views::corewm::RecreateWindowLayers(w1->GetNativeView(), false); - - // The order of the layers returned by RecreateWindowLayers() should match the - // order of the layers prior to calling RecreateWindowLayers(). - ASSERT_EQ("w1", w1_layer->name()); - ASSERT_EQ("v1 v4 w2 v7", ui::test::ChildLayerNamesAsString(*w1_layer)); - w2_layer = w1_layer->children()[2]; - ASSERT_EQ("v5", ui::test::ChildLayerNamesAsString(*w2_layer)); - v5_layer = w2_layer->children()[0]; - ASSERT_EQ("v6", ui::test::ChildLayerNamesAsString(*v5_layer)); - - views::corewm::DeepDeleteLayers(w1_layer); - // The views and the widgets are destroyed when AuraTestHelper::TearDown() - // destroys root_window(). -} |