diff options
author | oshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-30 22:10:14 +0000 |
---|---|---|
committer | oshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-30 22:10:14 +0000 |
commit | a857dbe9dab3f8df2b452d8fac0e2f1795ac8926 (patch) | |
tree | 3417cecbbab60f2ad69f05c1157eb8a7bcd9192f | |
parent | 800c8d730fc85e7bf9b548947f5842828346c485 (diff) | |
download | chromium_src-a857dbe9dab3f8df2b452d8fac0e2f1795ac8926.zip chromium_src-a857dbe9dab3f8df2b452d8fac0e2f1795ac8926.tar.gz chromium_src-a857dbe9dab3f8df2b452d8fac0e2f1795ac8926.tar.bz2 |
Decouple FocusManager from RootWindow.
- Added FocusChangeObserver
Store active window in ActivationController instead of in RootWindow as there will be multiple root windows.
BUG=123160
TEST=no functional change. all tests must pass.
Review URL: https://chromiumcodereview.appspot.com/10453019
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@139647 0039d316-1c4b-4281-b951-d872f2087c98
27 files changed, 277 insertions, 159 deletions
diff --git a/ash/monitor/monitor_controller.cc b/ash/monitor/monitor_controller.cc index 59c6b41..9bc85b4 100644 --- a/ash/monitor/monitor_controller.cc +++ b/ash/monitor/monitor_controller.cc @@ -5,13 +5,7 @@ #include "ash/monitor/monitor_controller.h" #include "ash/monitor/multi_monitor_manager.h" -#include "ash/monitor/secondary_monitor_view.h" #include "ash/shell.h" -#include "ash/wm/base_layout_manager.h" -#include "ash/wm/root_window_layout_manager.h" -#include "base/bind.h" -#include "base/stl_util.h" -#include "base/time.h" #include "ui/aura/env.h" #include "ui/aura/root_window.h" #include "ui/aura/window.h" @@ -20,24 +14,6 @@ namespace ash { namespace internal { -namespace { - -void SetupAsSecondaryMonitor(aura::RootWindow* root) { - root->SetFocusWhenShown(false); - root->SetLayoutManager(new internal::RootWindowLayoutManager(root)); - aura::Window* container = new aura::Window(NULL); - container->SetName("SecondaryMonitorContainer"); - container->Init(ui::LAYER_NOT_DRAWN); - root->AddChild(container); - container->SetLayoutManager(new internal::BaseLayoutManager(root)); - CreateSecondaryMonitorWidget(container); - container->Show(); - root->layout_manager()->OnWindowResized(); - root->ShowRootWindow(); -} - -} // namespace - MonitorController::MonitorController() { aura::Env::GetInstance()->monitor_manager()->AddObserver(this); Init(); @@ -66,7 +42,7 @@ void MonitorController::OnMonitorAdded(const gfx::Monitor& monitor) { aura::RootWindow* root = aura::Env::GetInstance()->monitor_manager()-> CreateRootWindowForMonitor(monitor); root_windows_[monitor.id()] = root; - SetupAsSecondaryMonitor(root); + Shell::GetInstance()->InitRootWindowForSecondaryMonitor(root); } void MonitorController::OnMonitorRemoved(const gfx::Monitor& monitor) { @@ -95,7 +71,7 @@ void MonitorController::Init() { aura::RootWindow* root = monitor_manager->CreateRootWindowForMonitor(monitor); root_windows_[monitor.id()] = root; - SetupAsSecondaryMonitor(root); + Shell::GetInstance()->InitRootWindowForSecondaryMonitor(root); } } } diff --git a/ash/shell.cc b/ash/shell.cc index 9d4f7de..0b137f18 100644 --- a/ash/shell.cc +++ b/ash/shell.cc @@ -19,6 +19,7 @@ #include "ash/magnifier/magnification_controller.h" #include "ash/monitor/monitor_controller.h" #include "ash/monitor/multi_monitor_manager.h" +#include "ash/monitor/secondary_monitor_view.h" #include "ash/screen_ash.h" #include "ash/shell_context_menu.h" #include "ash/shell_delegate.h" @@ -66,6 +67,7 @@ #include "third_party/skia/include/core/SkBitmap.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/env.h" +#include "ui/aura/focus_manager.h" #include "ui/aura/layout_manager.h" #include "ui/aura/monitor_manager.h" #include "ui/aura/root_window.h" @@ -652,12 +654,21 @@ aura::RootWindow* Shell::GetPrimaryRootWindow() { return GetInstance()->root_window_.get(); } +aura::RootWindow* Shell::GetActiveRootWindow() { + return GetInstance()->active_root_window_; +} + void Shell::Init() { // Install the custom factory first so that views::FocusManagers for Tray, // Launcher, and WallPaper could be created by the factory. views::FocusManagerFactory::Install(new AshFocusManagerFactory); aura::RootWindow* root_window = GetPrimaryRootWindow(); + active_root_window_ = root_window; + + focus_manager_.reset(new aura::FocusManager); + root_window_->set_focus_manager(focus_manager_.get()); + root_filter_ = new aura::shared::RootWindowEventFilter(root_window); #if !defined(OS_MACOSX) nested_dispatcher_controller_.reset(new NestedDispatcherController); @@ -665,7 +676,7 @@ void Shell::Init() { #endif shell_context_menu_.reset(new internal::ShellContextMenu); // Pass ownership of the filter to the root window. - GetPrimaryRootWindow()->SetEventFilter(root_filter_); + root_window->SetEventFilter(root_filter_); // KeyRewriterEventFilter must be the first one. DCHECK(!GetRootWindowEventFilterCount()); @@ -920,6 +931,21 @@ bool Shell::IsInMaximizedMode() const { return workspace_controller_->workspace_manager()->IsInMaximizedMode(); } +void Shell::InitRootWindowForSecondaryMonitor(aura::RootWindow* root) { + root->set_focus_manager(focus_manager_.get()); + root->SetFocusWhenShown(false); + root->SetLayoutManager(new internal::RootWindowLayoutManager(root)); + aura::Window* container = new aura::Window(NULL); + container->SetName("SecondaryMonitorContainer"); + container->Init(ui::LAYER_NOT_DRAWN); + root->AddChild(container); + container->SetLayoutManager(new internal::BaseLayoutManager(root)); + CreateSecondaryMonitorWidget(container); + container->Show(); + root->layout_manager()->OnWindowResized(); + root->ShowRootWindow(); +} + //////////////////////////////////////////////////////////////////////////////// // Shell, private: diff --git a/ash/shell.h b/ash/shell.h index 12e7c15..e212335 100644 --- a/ash/shell.h +++ b/ash/shell.h @@ -25,6 +25,7 @@ class SkBitmap; namespace aura { class EventFilter; +class FocusManager; class Monitor; class RootWindow; class Window; @@ -133,10 +134,20 @@ class ASH_EXPORT Shell { static void DeleteInstance(); - // Gets the primary RootWindow. The primary RootWindow is the root window + // Gets the primary RootWindow. The primary RootWindow is the one // that has a launcher. static aura::RootWindow* GetPrimaryRootWindow(); + // Gets the active RootWindow. The active RootWindow is the one that + // contains the current active window as a decendant child. The active + // RootWindow remains the same even when the active window becomes NULL, + // until the another window who has a different root window becomes active. + static aura::RootWindow* GetActiveRootWindow(); + + void set_active_root_window(aura::RootWindow* active_root_window) { + active_root_window_ = active_root_window; + } + internal::RootWindowLayoutManager* root_window_layout() const { return root_window_layout_; } @@ -294,6 +305,9 @@ class ASH_EXPORT Shell { browser_context_ = browser_context; } + // Initialize the root window to be used for a secondary monitor. + void InitRootWindowForSecondaryMonitor(aura::RootWindow* root); + private: FRIEND_TEST_ALL_PREFIXES(RootWindowEventFilterTest, MouseEventCursors); FRIEND_TEST_ALL_PREFIXES(RootWindowEventFilterTest, TransformActivate); @@ -320,6 +334,9 @@ class ASH_EXPORT Shell { scoped_ptr<aura::RootWindow> root_window_; ScreenAsh* screen_; + // Active root window. Never become NULL. + aura::RootWindow* active_root_window_; + aura::shared::RootWindowEventFilter* root_filter_; // not owned std::vector<WindowAndBoundsPair> to_restore_; @@ -358,6 +375,7 @@ class ASH_EXPORT Shell { scoped_ptr<HighContrastController> high_contrast_controller_; scoped_ptr<internal::MagnificationController> magnification_controller_; scoped_ptr<internal::ScreenDimmer> screen_dimmer_; + scoped_ptr<aura::FocusManager> focus_manager_; // An event filter that rewrites or drops a key event. scoped_ptr<internal::KeyRewriterEventFilter> key_rewriter_filter_; diff --git a/ash/wm/activation_controller.cc b/ash/wm/activation_controller.cc index 8507508..0758571 100644 --- a/ash/wm/activation_controller.cc +++ b/ash/wm/activation_controller.cc @@ -12,6 +12,7 @@ #include "ui/aura/client/activation_delegate.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/env.h" +#include "ui/aura/focus_manager.h" #include "ui/aura/root_window.h" #include "ui/aura/window.h" #include "ui/aura/window_delegate.h" @@ -117,15 +118,16 @@ void StackTransientParentsBelowModalWindow(aura::Window* window) { ActivationController::ActivationController() : updating_activation_(false), + active_window_(NULL), ALLOW_THIS_IN_INITIALIZER_LIST(observer_manager_(this)) { aura::client::SetActivationClient(Shell::GetPrimaryRootWindow(), this); aura::Env::GetInstance()->AddObserver(this); - Shell::GetPrimaryRootWindow()->AddRootWindowObserver(this); + Shell::GetPrimaryRootWindow()->GetFocusManager()->AddObserver(this); } ActivationController::~ActivationController() { - Shell::GetPrimaryRootWindow()->RemoveRootWindowObserver(this); aura::Env::GetInstance()->RemoveObserver(this); + Shell::GetPrimaryRootWindow()->GetFocusManager()->RemoveObserver(this); } // static @@ -165,8 +167,7 @@ void ActivationController::DeactivateWindow(aura::Window* window) { } aura::Window* ActivationController::GetActiveWindow() { - return Shell::GetPrimaryRootWindow()->GetProperty( - aura::client::kRootWindowActiveWindowKey); + return active_window_; } bool ActivationController::OnWillFocusWindow(aura::Window* window, @@ -192,10 +193,15 @@ void ActivationController::OnWindowVisibilityChanged(aura::Window* window, } void ActivationController::OnWindowDestroying(aura::Window* window) { - if (wm::IsActiveWindow(window)) { + // Don't use wm::IsActiveWidnow in case the |window| has + // removed from the root tree. + if (active_window_ == window) { + active_window_ = NULL; // Clear the property before activating something else, since // ActivateWindow() will attempt to notify the window stored in this value // otherwise. + // TODO(oshima): NativeWidgetAura relies on this property now. + // Fix NativeWidgetAura not to depend on this and remove this. Shell::GetPrimaryRootWindow()->ClearProperty( aura::client::kRootWindowActiveWindowKey); ActivateWindow(GetTopmostWindowToActivate(window)); @@ -258,8 +264,18 @@ void ActivationController::ActivateWindowWithEvent(aura::Window* window, !window->Contains(window->GetFocusManager()->GetFocusedWindow())) { window->GetFocusManager()->SetFocusedWindow(window, event); } + + active_window_ = window; + if (window) { + DCHECK(window->GetRootWindow()); + Shell::GetInstance()->set_active_root_window(window->GetRootWindow()); + } + + // TODO(oshima): Remove this (see comment in OnWindowDestroying above) Shell::GetPrimaryRootWindow()->SetProperty( - aura::client::kRootWindowActiveWindowKey, window); + aura::client::kRootWindowActiveWindowKey, + window); + // Invoke OnLostActive after we've changed the active window. That way if the // delegate queries for active state it doesn't think the window is still // active. diff --git a/ash/wm/activation_controller.h b/ash/wm/activation_controller.h index 32fe65e..b53c787 100644 --- a/ash/wm/activation_controller.h +++ b/ash/wm/activation_controller.h @@ -11,7 +11,7 @@ #include "base/compiler_specific.h" #include "ui/aura/client/activation_client.h" #include "ui/aura/env_observer.h" -#include "ui/aura/root_window_observer.h" +#include "ui/aura/focus_change_observer.h" #include "ui/aura/window_observer.h" #include "ash/ash_export.h" @@ -23,7 +23,7 @@ class ASH_EXPORT ActivationController : public aura::client::ActivationClient, public aura::WindowObserver, public aura::EnvObserver, - public aura::RootWindowObserver { + public aura::FocusChangeObserver { public: ActivationController(); virtual ~ActivationController(); @@ -50,7 +50,7 @@ class ASH_EXPORT ActivationController // Overridden from aura::EnvObserver: virtual void OnWindowInitialized(aura::Window* window) OVERRIDE; - // Overridden from aura::RootWindowObserver: + // Overridden from aura::FocusChangeObserver: virtual void OnWindowFocused(aura::Window* window) OVERRIDE; private: @@ -75,6 +75,8 @@ class ASH_EXPORT ActivationController // change notifications causing activation. bool updating_activation_; + aura::Window* active_window_; + ScopedObserver<aura::Window, aura::WindowObserver> observer_manager_; DISALLOW_COPY_AND_ASSIGN(ActivationController); diff --git a/ash/wm/app_list_controller.cc b/ash/wm/app_list_controller.cc index e95f4c4..fb6159b 100644 --- a/ash/wm/app_list_controller.cc +++ b/ash/wm/app_list_controller.cc @@ -15,6 +15,7 @@ #include "ui/app_list/app_list_view.h" #include "ui/app_list/icon_cache.h" #include "ui/aura/event.h" +#include "ui/aura/focus_manager.h" #include "ui/aura/root_window.h" #include "ui/aura/window.h" #include "ui/compositor/layer.h" @@ -152,7 +153,7 @@ void AppListController::SetView(app_list::AppListView* view) { widget->AddObserver(this); Shell::GetInstance()->AddRootWindowEventFilter(this); widget->GetNativeView()->GetRootWindow()->AddRootWindowObserver(this); - + widget->GetNativeView()->GetFocusManager()->AddObserver(this); widget->SetOpacity(0); ScheduleAnimation(); @@ -171,6 +172,7 @@ void AppListController::ResetView() { GetLayer(widget)->GetAnimator()->RemoveObserver(this); Shell::GetInstance()->RemoveRootWindowEventFilter(this); widget->GetNativeView()->GetRootWindow()->RemoveRootWindowObserver(this); + widget->GetNativeView()->GetFocusManager()->RemoveObserver(this); view_ = NULL; app_list::IconCache::GetInstance()->PurgeAllUnused(); @@ -292,17 +294,7 @@ ui::GestureStatus AppListController::PreHandleGestureEvent( } //////////////////////////////////////////////////////////////////////////////// -// AppListController, aura::RootWindowObserver implementation: -void AppListController::OnRootWindowResized(const aura::RootWindow* root, - const gfx::Size& old_size) { - if (view_ && is_visible_) { - views::Widget* launcher_widget = - Shell::GetInstance()->launcher()->widget(); - view_->UpdateBounds(GetFullScreenBoundsForWidget(launcher_widget), - GetWorkAreaBoundsForWidget(launcher_widget)); - } -} - +// AppListController, aura::FocusObserver implementation: void AppListController::OnWindowFocused(aura::Window* window) { if (view_ && is_visible_) { aura::Window* applist_container = Shell::GetInstance()->GetContainer( @@ -317,6 +309,18 @@ void AppListController::OnWindowFocused(aura::Window* window) { } //////////////////////////////////////////////////////////////////////////////// +// AppListController, aura::RootWindowObserver implementation: +void AppListController::OnRootWindowResized(const aura::RootWindow* root, + const gfx::Size& old_size) { + if (view_ && is_visible_) { + views::Widget* launcher_widget = + Shell::GetInstance()->launcher()->widget(); + view_->UpdateBounds(GetFullScreenBoundsForWidget(launcher_widget), + GetWorkAreaBoundsForWidget(launcher_widget)); + } +} + +//////////////////////////////////////////////////////////////////////////////// // AppListController, ui::ImplicitAnimationObserver implementation: void AppListController::OnImplicitAnimationsCompleted() { diff --git a/ash/wm/app_list_controller.h b/ash/wm/app_list_controller.h index 3c7e7c2..bf6e863 100644 --- a/ash/wm/app_list_controller.h +++ b/ash/wm/app_list_controller.h @@ -11,6 +11,7 @@ #include "base/compiler_specific.h" #include "base/timer.h" #include "ui/aura/event_filter.h" +#include "ui/aura/focus_change_observer.h" #include "ui/aura/root_window_observer.h" #include "ui/compositor/layer_animation_observer.h" #include "ui/views/widget/widget.h" @@ -27,6 +28,7 @@ namespace internal { // While the UI is visible, it monitors things such as app list widget's // activation state and desktop mouse click to auto dismiss the UI. class AppListController : public aura::EventFilter, + public aura::FocusChangeObserver, public aura::RootWindowObserver, public ui::ImplicitAnimationObserver, public views::Widget::Observer, @@ -86,10 +88,12 @@ class AppListController : public aura::EventFilter, aura::Window* target, aura::GestureEvent* event) OVERRIDE; + // aura::FocusChangeObserver overrides: + virtual void OnWindowFocused(aura::Window* window) OVERRIDE; + // aura::RootWindowObserver overrides: virtual void OnRootWindowResized(const aura::RootWindow* root, const gfx::Size& old_size) OVERRIDE; - virtual void OnWindowFocused(aura::Window* window) OVERRIDE; // ui::ImplicitAnimationObserver overrides: virtual void OnImplicitAnimationsCompleted() OVERRIDE; @@ -117,4 +121,3 @@ class AppListController : public aura::EventFilter, } // namespace ash #endif // ASH_WM_APP_LIST_CONTROLLER_H_ - diff --git a/ash/wm/root_window_event_filter_unittest.cc b/ash/wm/root_window_event_filter_unittest.cc index 5f61056..10fb0442 100644 --- a/ash/wm/root_window_event_filter_unittest.cc +++ b/ash/wm/root_window_event_filter_unittest.cc @@ -11,6 +11,7 @@ #include "ui/aura/client/activation_client.h" #include "ui/aura/client/activation_delegate.h" #include "ui/aura/event.h" +#include "ui/aura/focus_manager.h" #include "ui/aura/root_window.h" #include "ui/aura/shared/input_method_event_filter.h" #include "ui/aura/shared/root_window_event_filter.h" @@ -112,7 +113,7 @@ TEST_F(RootWindowEventFilterTest, Focus) { w121.get()); generator.ClickLeftButton(); - aura::internal::FocusManager* focus_manager = w121->GetFocusManager(); + aura::FocusManager* focus_manager = w121->GetFocusManager(); EXPECT_EQ(w121.get(), focus_manager->GetFocusedWindow()); // The key press should be sent to the focused sub-window. @@ -191,7 +192,7 @@ TEST_F(RootWindowEventFilterTest, ActivateOnMouse) { &wd, -1, gfx::Rect(70, 70, 50, 50), NULL)); d2.SetWindow(w2.get()); - aura::internal::FocusManager* focus_manager = w1->GetFocusManager(); + aura::FocusManager* focus_manager = w1->GetFocusManager(); d1.Clear(); d2.Clear(); @@ -307,7 +308,7 @@ TEST_F(RootWindowEventFilterTest, ActivateOnTouch) { &wd, -2, gfx::Rect(70, 70, 50, 50), NULL)); d2.SetWindow(w2.get()); - aura::internal::FocusManager* focus_manager = w1->GetFocusManager(); + aura::FocusManager* focus_manager = w1->GetFocusManager(); d1.Clear(); d2.Clear(); diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc index 8313fa5..91c87b1 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc @@ -43,6 +43,7 @@ #include "ui/views/views_delegate.h" #if defined(USE_AURA) +#include "ui/aura/focus_manager.h" #include "ui/aura/root_window.h" #endif @@ -353,7 +354,7 @@ void OmniboxViewViews::HandleFocusOut() { if (widget) { aura::RootWindow* root = widget->GetNativeView()->GetRootWindow(); if (root) - native_view = root->focused_window(); + native_view = root->GetFocusManager()->GetFocusedWindow(); } #endif model_->OnWillKillFocus(native_view); diff --git a/ui/aura/aura.gyp b/ui/aura/aura.gyp index b77e7e7..3762b0d 100644 --- a/ui/aura/aura.gyp +++ b/ui/aura/aura.gyp @@ -75,6 +75,8 @@ 'event_filter.h', 'event_mac.mm', 'event_mac.h', + 'focus_change_observer.h', + 'focus_manager.cc', 'focus_manager.h', 'layout_manager.cc', 'layout_manager.h', diff --git a/ui/aura/desktop/desktop_activation_client.cc b/ui/aura/desktop/desktop_activation_client.cc index 183a0ee..2ffa331 100644 --- a/ui/aura/desktop/desktop_activation_client.cc +++ b/ui/aura/desktop/desktop_activation_client.cc @@ -16,11 +16,11 @@ DesktopActivationClient::DesktopActivationClient(RootWindow* root_window) : root_window_(root_window), current_active_(NULL), updating_activation_(false) { - root_window->AddRootWindowObserver(this); + root_window_->GetFocusManager()->AddObserver(this); } DesktopActivationClient::~DesktopActivationClient() { - root_window_->RemoveRootWindowObserver(this); + root_window_->GetFocusManager()->RemoveObserver(this); } void DesktopActivationClient::ActivateWindow(Window* window) { diff --git a/ui/aura/desktop/desktop_activation_client.h b/ui/aura/desktop/desktop_activation_client.h index 5d2f12c..d18858b 100644 --- a/ui/aura/desktop/desktop_activation_client.h +++ b/ui/aura/desktop/desktop_activation_client.h @@ -9,6 +9,7 @@ #include "base/basictypes.h" #include "ui/aura/aura_export.h" #include "ui/aura/client/activation_client.h" +#include "ui/aura/focus_change_observer.h" #include "ui/aura/root_window_observer.h" namespace aura { @@ -18,7 +19,7 @@ class RootWindow; // RootWindow. Used only on the Desktop where there can be multiple RootWindow // objects. class AURA_EXPORT DesktopActivationClient : public client::ActivationClient, - public RootWindowObserver { + public FocusChangeObserver { public: explicit DesktopActivationClient(RootWindow* root_window); virtual ~DesktopActivationClient(); @@ -30,7 +31,7 @@ class AURA_EXPORT DesktopActivationClient : public client::ActivationClient, virtual bool OnWillFocusWindow(Window* window, const Event* event) OVERRIDE; virtual bool CanActivateWindow(Window* window) const OVERRIDE; - // RootWindowObserver: + // FocusChangeObserver: virtual void OnWindowFocused(aura::Window* window) OVERRIDE; protected: diff --git a/ui/aura/env_observer.h b/ui/aura/env_observer.h index 9a4541a..351f14b 100644 --- a/ui/aura/env_observer.h +++ b/ui/aura/env_observer.h @@ -6,7 +6,6 @@ #define UI_AURA_ENV_OBSERVER_H_ #pragma once -#include "base/observer_list.h" #include "ui/aura/aura_export.h" namespace aura { diff --git a/ui/aura/event_filter_unittest.cc b/ui/aura/event_filter_unittest.cc index 196ca18..6b61e9a 100644 --- a/ui/aura/event_filter_unittest.cc +++ b/ui/aura/event_filter_unittest.cc @@ -7,6 +7,7 @@ #include "base/basictypes.h" #include "base/compiler_specific.h" #include "ui/aura/event.h" +#include "ui/aura/focus_manager.h" #include "ui/aura/root_window.h" #include "ui/aura/test/aura_test_base.h" #include "ui/aura/test/event_generator.h" diff --git a/ui/aura/focus_change_observer.h b/ui/aura/focus_change_observer.h new file mode 100644 index 0000000..312f8b3 --- /dev/null +++ b/ui/aura/focus_change_observer.h @@ -0,0 +1,26 @@ +// 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_AURA_FOCUS_CHANGE_OBSERVER_H_ +#define UI_AURA_FOCUS_CHANGE_OBSERVER_H_ +#pragma once + +#include "ui/aura/aura_export.h" + +namespace aura { + +class Window; + +class AURA_EXPORT FocusChangeObserver { + public: + // Called when |window| gains focus. + virtual void OnWindowFocused(Window* window) = 0; + + protected: + virtual ~FocusChangeObserver() {} +}; + +} // namespace aura + +#endif // UI_AURA_FOCUS_CHANGE_OBSERVER_H_ diff --git a/ui/aura/focus_manager.cc b/ui/aura/focus_manager.cc new file mode 100644 index 0000000..475c0e3 --- /dev/null +++ b/ui/aura/focus_manager.cc @@ -0,0 +1,66 @@ +// 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/aura/focus_manager.h" + +#include "ui/aura/client/activation_client.h" +#include "ui/aura/focus_change_observer.h" +#include "ui/aura/window_delegate.h" + +namespace aura { +FocusManager::FocusManager() : focused_window_(NULL) { +} + +FocusManager::~FocusManager() { +} + +void FocusManager::AddObserver(FocusChangeObserver* observer) { + observers_.AddObserver(observer); +} + +void FocusManager::RemoveObserver(FocusChangeObserver* observer) { + observers_.RemoveObserver(observer); +} + +void FocusManager::SetFocusedWindow(Window* focused_window, + const Event* event) { + if (focused_window == focused_window_) + return; + if (focused_window && !focused_window->CanFocus()) + return; + // The NULL-check of |focused_window| is essential here before asking the + // activation client, since it is valid to clear the focus by calling + // SetFocusedWindow() to NULL. + + if (focused_window) { + RootWindow* root = focused_window->GetRootWindow(); + DCHECK(root); + if (client::GetActivationClient(root) && + !client::GetActivationClient(root)->OnWillFocusWindow( + focused_window, event)) { + return; + } + } + + Window* old_focused_window = focused_window_; + focused_window_ = focused_window; + if (old_focused_window && old_focused_window->delegate()) + old_focused_window->delegate()->OnBlur(); + if (focused_window_ && focused_window_->delegate()) + focused_window_->delegate()->OnFocus(); + if (focused_window_) { + FOR_EACH_OBSERVER(FocusChangeObserver, observers_, + OnWindowFocused(focused_window)); + } +} + +Window* FocusManager::GetFocusedWindow() { + return focused_window_; +} + +bool FocusManager::IsFocusedWindow(const Window* window) const { + return focused_window_ == window; +} + +} // namespace ash diff --git a/ui/aura/focus_manager.h b/ui/aura/focus_manager.h index d3ccefc..c2a4290 100644 --- a/ui/aura/focus_manager.h +++ b/ui/aura/focus_manager.h @@ -7,37 +7,46 @@ #pragma once #include "base/basictypes.h" +#include "base/observer_list.h" #include "ui/aura/aura_export.h" namespace aura { class Event; +class FocusChangeObserver; class Window; -namespace internal { - // An interface implemented by the Desktop to expose the focused window and // allow for it to be changed. class AURA_EXPORT FocusManager { public: + FocusManager(); + ~FocusManager(); + + void AddObserver(FocusChangeObserver* observer); + void RemoveObserver(FocusChangeObserver* observer); + // Sets the currently focused window. Before the currently focused window is // changed, the previous focused window's delegate is sent a blur // notification, and after it is changed the new focused window is sent a // focused notification. Nothing happens if |window| and GetFocusedWindow() // match. - virtual void SetFocusedWindow(Window* window, const Event* event) = 0; + void SetFocusedWindow(Window* window, const Event* event); // Returns the currently focused window or NULL if there is none. - virtual Window* GetFocusedWindow() = 0; + Window* GetFocusedWindow(); // Returns true if |window| is the focused window. - virtual bool IsFocusedWindow(const Window* window) const = 0; + bool IsFocusedWindow(const Window* window) const; protected: - virtual ~FocusManager() {} + aura::Window* focused_window_; + + ObserverList<FocusChangeObserver> observers_; + + DISALLOW_COPY_AND_ASSIGN(FocusManager); }; -} // namespace internal } // namespace aura #endif // UI_AURA_FOCUS_MANAGER_H_ diff --git a/ui/aura/root_window.cc b/ui/aura/root_window.cc index fec4337..b47fc60 100644 --- a/ui/aura/root_window.cc +++ b/ui/aura/root_window.cc @@ -121,7 +121,6 @@ RootWindow::RootWindow(const gfx::Rect& initial_bounds) capture_window_(NULL), mouse_pressed_handler_(NULL), mouse_moved_handler_(NULL), - focused_window_(NULL), ALLOW_THIS_IN_INITIALIZER_LIST( gesture_recognizer_(ui::GestureRecognizer::Create(this))), synthesize_mouse_move_(false), @@ -272,11 +271,12 @@ bool RootWindow::DispatchKeyEvent(KeyEvent* event) { if (translated_event.key_code() == ui::VKEY_UNKNOWN) return false; client::EventClient* client = client::GetEventClient(GetRootWindow()); - if (client && !client->CanProcessEventsWithinSubtree(focused_window_)) { - SetFocusedWindow(NULL, NULL); + Window* focused_window = focus_manager_->GetFocusedWindow(); + if (client && !client->CanProcessEventsWithinSubtree(focused_window)) { + GetFocusManager()->SetFocusedWindow(NULL, NULL); return false; } - return ProcessKeyEvent(focused_window_, &translated_event); + return ProcessKeyEvent(focused_window, &translated_event); } bool RootWindow::DispatchScrollEvent(ScrollEvent* event) { @@ -590,6 +590,7 @@ void RootWindow::OnCompositingAborted(ui::Compositor*) { //////////////////////////////////////////////////////////////////////////////// // RootWindow, ui::LayerDelegate implementation: + void RootWindow::OnDeviceScaleFactorChanged( float device_scale_factor) { if (cursor_shown_) @@ -601,6 +602,21 @@ void RootWindow::OnDeviceScaleFactorChanged( } //////////////////////////////////////////////////////////////////////////////// +// RootWindow, overridden from aura::Window: + +bool RootWindow::CanFocus() const { + return IsVisible(); +} + +bool RootWindow::CanReceiveEvents() const { + return IsVisible(); +} + +FocusManager* RootWindow::GetFocusManager() { + return focus_manager_; +} + +//////////////////////////////////////////////////////////////////////////////// // RootWindow, private: void RootWindow::HandleMouseCaptureChanged(Window* old_capture_window) { @@ -817,7 +833,8 @@ void RootWindow::OnWindowRemovedFromRootWindow(Window* detached) { void RootWindow::OnWindowHidden(Window* invisible, bool destroyed) { // Update the focused window state if the invisible window contains // focused_window. - if (invisible->Contains(focused_window_)) { + Window* focused_window = focus_manager_->GetFocusedWindow(); + if (invisible->Contains(focused_window)) { Window* focus_to = invisible->transient_parent(); if (focus_to) { // Has to be removed from the transient parent before focusing, otherwise @@ -836,7 +853,7 @@ void RootWindow::OnWindowHidden(Window* invisible, bool destroyed) { NULL)))) { focus_to = NULL; } - SetFocusedWindow(focus_to, NULL); + GetFocusManager()->SetFocusedWindow(focus_to, NULL); } // If the ancestor of the capture window is hidden, // release the capture. @@ -858,18 +875,6 @@ void RootWindow::OnWindowAddedToRootWindow(Window* attached) { PostMouseMoveEventAfterWindowChange(); } -bool RootWindow::CanFocus() const { - return IsVisible(); -} - -bool RootWindow::CanReceiveEvents() const { - return IsVisible(); -} - -internal::FocusManager* RootWindow::GetFocusManager() { - return this; -} - bool RootWindow::DispatchLongPressGestureEvent(ui::GestureEvent* event) { return DispatchGestureEvent(static_cast<GestureEvent*>(event)); } @@ -909,41 +914,6 @@ void RootWindow::OnLayerAnimationAborted( ui::LayerAnimationSequence* animation) { } -void RootWindow::SetFocusedWindow(Window* focused_window, - const aura::Event* event) { - if (focused_window == focused_window_) - return; - if (focused_window && !focused_window->CanFocus()) - return; - // The NULL-check of |focused_window| is essential here before asking the - // activation client, since it is valid to clear the focus by calling - // SetFocusedWindow() to NULL. - if (focused_window && client::GetActivationClient(this) && - !client::GetActivationClient(this)->OnWillFocusWindow(focused_window, - event)) { - return; - } - - Window* old_focused_window = focused_window_; - focused_window_ = focused_window; - if (old_focused_window && old_focused_window->delegate()) - old_focused_window->delegate()->OnBlur(); - if (focused_window_ && focused_window_->delegate()) - focused_window_->delegate()->OnFocus(); - if (focused_window_) { - FOR_EACH_OBSERVER(RootWindowObserver, observers_, - OnWindowFocused(focused_window_)); - } -} - -Window* RootWindow::GetFocusedWindow() { - return focused_window_; -} - -bool RootWindow::IsFocusedWindow(const Window* window) const { - return focused_window_ == window; -} - bool RootWindow::DispatchMouseEventImpl(MouseEvent* event) { float scale = ui::GetDeviceScaleFactor(layer()); ui::Transform transform = layer()->transform(); diff --git a/ui/aura/root_window.h b/ui/aura/root_window.h index 05348a3..2666c81 100644 --- a/ui/aura/root_window.h +++ b/ui/aura/root_window.h @@ -14,7 +14,6 @@ #include "base/memory/weak_ptr.h" #include "base/message_loop.h" #include "ui/aura/aura_export.h" -#include "ui/aura/focus_manager.h" #include "ui/aura/window.h" #include "ui/base/cursor/cursor.h" #include "ui/base/events.h" @@ -38,15 +37,15 @@ class Transform; namespace aura { +class FocusManager; +class GestureEvent; +class KeyEvent; +class MouseEvent; class RootWindow; class RootWindowHost; class RootWindowObserver; -class KeyEvent; -class MouseEvent; -class StackingClient; class ScrollEvent; class TouchEvent; -class GestureEvent; // This class represents a lock on the compositor, that can be used to prevent a // compositing pass from happening while we're waiting for an asynchronous @@ -77,7 +76,6 @@ class AURA_EXPORT CompositorLock : class AURA_EXPORT RootWindow : public ui::CompositorDelegate, public ui::CompositorObserver, public Window, - public internal::FocusManager, public ui::GestureEventHelper, public ui::LayerAnimationObserver { public: @@ -97,7 +95,10 @@ class AURA_EXPORT RootWindow : public ui::CompositorDelegate, bool cursor_shown() const { return cursor_shown_; } Window* mouse_pressed_handler() { return mouse_pressed_handler_; } Window* capture_window() { return capture_window_; } - Window* focused_window() { return focused_window_; } + + void set_focus_manager(FocusManager* focus_manager) { + focus_manager_ = focus_manager; + } // Initializes the root window. void Init(); @@ -263,6 +264,11 @@ class AURA_EXPORT RootWindow : public ui::CompositorDelegate, // Overridden from ui::LayerDelegate: virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE; + // Overridden from Window: + virtual bool CanFocus() const OVERRIDE; + virtual bool CanReceiveEvents() const OVERRIDE; + virtual FocusManager* GetFocusManager() OVERRIDE; + private: friend class Window; friend class CompositorLock; @@ -290,11 +296,6 @@ class AURA_EXPORT RootWindow : public ui::CompositorDelegate, // |destroyed| is set to true when the window is being destroyed. void OnWindowHidden(Window* invisible, bool destroyed); - // Overridden from Window: - virtual bool CanFocus() const OVERRIDE; - virtual bool CanReceiveEvents() const OVERRIDE; - virtual internal::FocusManager* GetFocusManager() OVERRIDE; - // Overridden from ui::GestureEventHelper. virtual ui::GestureEvent* CreateGestureEvent( ui::EventType type, @@ -322,12 +323,6 @@ class AURA_EXPORT RootWindow : public ui::CompositorDelegate, virtual void OnLayerAnimationAborted( ui::LayerAnimationSequence* animation) OVERRIDE; - // Overridden from FocusManager: - virtual void SetFocusedWindow(Window* window, - const aura::Event* event) OVERRIDE; - virtual Window* GetFocusedWindow() OVERRIDE; - virtual bool IsFocusedWindow(const Window* window) const OVERRIDE; - // We hold and aggregate mouse drags as a way of throttling resizes when // HoldMouseMoves() is called. The following methods are used to dispatch held // and newly incoming mouse events, typically when an event other than a mouse @@ -388,7 +383,7 @@ class AURA_EXPORT RootWindow : public ui::CompositorDelegate, Window* mouse_pressed_handler_; Window* mouse_moved_handler_; - Window* focused_window_; + FocusManager* focus_manager_; // The gesture_recognizer_ for this. scoped_ptr<ui::GestureRecognizer> gesture_recognizer_; diff --git a/ui/aura/root_window_observer.h b/ui/aura/root_window_observer.h index 39c9a4a..813aa0c 100644 --- a/ui/aura/root_window_observer.h +++ b/ui/aura/root_window_observer.h @@ -26,9 +26,6 @@ class AURA_EXPORT RootWindowObserver { // window. virtual void OnRootWindowHostClosed(const RootWindow* root) {} - // Invoked when a window is focused. - virtual void OnWindowFocused(Window* window) {} - // Invoked when the keyboard mapping has changed. virtual void OnKeyboardMappingChanged(const RootWindow* root) {} diff --git a/ui/aura/root_window_unittest.cc b/ui/aura/root_window_unittest.cc index 904ff5f..f1c456b 100644 --- a/ui/aura/root_window_unittest.cc +++ b/ui/aura/root_window_unittest.cc @@ -11,6 +11,7 @@ #include "ui/aura/env.h" #include "ui/aura/event.h" #include "ui/aura/event_filter.h" +#include "ui/aura/focus_manager.h" #include "ui/aura/test/aura_test_base.h" #include "ui/aura/test/event_generator.h" #include "ui/aura/test/test_window_delegate.h" diff --git a/ui/aura/test/aura_test_helper.cc b/ui/aura/test/aura_test_helper.cc index c4e094c..12f4657 100644 --- a/ui/aura/test/aura_test_helper.cc +++ b/ui/aura/test/aura_test_helper.cc @@ -5,18 +5,19 @@ #include "ui/aura/test/aura_test_helper.h" #include "base/message_loop.h" +#include "ui/aura/client/aura_constants.h" #include "ui/aura/env.h" +#include "ui/aura/focus_manager.h" +#include "ui/aura/monitor_manager.h" #include "ui/aura/root_window.h" -#include "ui/compositor/layer_animator.h" -#include "ui/gfx/screen.h" -#include "ui/aura/client/aura_constants.h" #include "ui/aura/single_monitor_manager.h" -#include "ui/aura/monitor_manager.h" -#include "ui/aura/test/test_screen.h" #include "ui/aura/test/test_activation_client.h" +#include "ui/aura/test/test_screen.h" #include "ui/aura/test/test_stacking_client.h" #include "ui/aura/ui_controls_aura.h" #include "ui/base/test/dummy_input_method.h" +#include "ui/compositor/layer_animator.h" +#include "ui/gfx/screen.h" #include "ui/ui_controls/ui_controls.h" namespace aura { @@ -47,6 +48,8 @@ void AuraTestHelper::SetUp() { gfx::Screen::SetInstance(new aura::TestScreen(root_window_.get())); ui_controls::InstallUIControlsAura(CreateUIControlsAura(root_window_.get())); + focus_manager_.reset(new FocusManager); + root_window_->set_focus_manager(focus_manager_.get()); stacking_client_.reset(new TestStackingClient(root_window_.get())); test_activation_client_.reset( new aura::test::TestActivationClient(root_window_.get())); @@ -65,6 +68,7 @@ void AuraTestHelper::TearDown() { test_input_method_.reset(); stacking_client_.reset(); test_activation_client_.reset(); + focus_manager_.reset(); root_window_.reset(); aura::Env::DeleteInstance(); } diff --git a/ui/aura/test/aura_test_helper.h b/ui/aura/test/aura_test_helper.h index 4d2fa46..94f2846 100644 --- a/ui/aura/test/aura_test_helper.h +++ b/ui/aura/test/aura_test_helper.h @@ -20,10 +20,11 @@ class InputMethod; } namespace aura { +class FocusManager; class RootWindow; namespace test { -class TestStackingClient; class TestActivationClient; +class TestStackingClient; // A helper class owned by tests that does common initialization required for // Aura use. This class creates a root window with clients and other objects @@ -54,6 +55,7 @@ class AuraTestHelper { scoped_ptr<TestStackingClient> stacking_client_; scoped_ptr<TestActivationClient> test_activation_client_; scoped_ptr<ui::InputMethod> test_input_method_; + scoped_ptr<FocusManager> focus_manager_; #if defined(OS_WIN) ui::ScopedOleInitializer ole_initializer_; diff --git a/ui/aura/window.cc b/ui/aura/window.cc index 1902199..82c442c 100644 --- a/ui/aura/window.cc +++ b/ui/aura/window.cc @@ -16,6 +16,7 @@ #include "ui/aura/env.h" #include "ui/aura/event.h" #include "ui/aura/event_filter.h" +#include "ui/aura/focus_manager.h" #include "ui/aura/layout_manager.h" #include "ui/aura/root_window.h" #include "ui/aura/window_delegate.h" @@ -465,7 +466,7 @@ void Window::Blur() { } bool Window::HasFocus() const { - const internal::FocusManager* focus_manager = GetFocusManager(); + const FocusManager* focus_manager = GetFocusManager(); return focus_manager ? focus_manager->IsFocusedWindow(this) : false; } @@ -497,12 +498,12 @@ bool Window::CanReceiveEvents() const { return parent_ && IsVisible() && parent_->CanReceiveEvents(); } -internal::FocusManager* Window::GetFocusManager() { - return const_cast<internal::FocusManager*>( +FocusManager* Window::GetFocusManager() { + return const_cast<FocusManager*>( static_cast<const Window*>(this)->GetFocusManager()); } -const internal::FocusManager* Window::GetFocusManager() const { +const FocusManager* Window::GetFocusManager() const { return parent_ ? parent_->GetFocusManager() : NULL; } diff --git a/ui/aura/window.h b/ui/aura/window.h index ba2cfb0..06f8812 100644 --- a/ui/aura/window.h +++ b/ui/aura/window.h @@ -38,15 +38,12 @@ class Transform; namespace aura { class EventFilter; +class FocusManager; class LayoutManager; class RootWindow; class WindowDelegate; class WindowObserver; -namespace internal { -class FocusManager; -} - // Defined in window_property.h (which we do not include) template<typename T> struct WindowProperty; @@ -291,8 +288,8 @@ class AURA_EXPORT Window : public ui::LayerDelegate, // Returns the FocusManager for the Window, which may be attached to a parent // Window. Can return NULL if the Window has no FocusManager. - virtual internal::FocusManager* GetFocusManager(); - virtual const internal::FocusManager* GetFocusManager() const; + virtual FocusManager* GetFocusManager(); + virtual const FocusManager* GetFocusManager() const; // Does a capture on the window. This does nothing if the window isn't showing // (VISIBILITY_SHOWN) or isn't contained in a valid window hierarchy. diff --git a/ui/aura/window_unittest.cc b/ui/aura/window_unittest.cc index 6e5bcbe..0b9cfbc 100644 --- a/ui/aura/window_unittest.cc +++ b/ui/aura/window_unittest.cc @@ -11,7 +11,6 @@ #include "ui/aura/client/stacking_client.h" #include "ui/aura/client/visibility_client.h" #include "ui/aura/event.h" -#include "ui/aura/focus_manager.h" #include "ui/aura/layout_manager.h" #include "ui/aura/root_window.h" #include "ui/aura/root_window_observer.h" diff --git a/ui/views/widget/native_widget_aura.cc b/ui/views/widget/native_widget_aura.cc index 75de8e5..90b17b9 100644 --- a/ui/views/widget/native_widget_aura.cc +++ b/ui/views/widget/native_widget_aura.cc @@ -15,6 +15,7 @@ #include "ui/aura/client/window_types.h" #include "ui/aura/env.h" #include "ui/aura/event.h" +#include "ui/aura/focus_manager.h" #include "ui/aura/root_window.h" #include "ui/aura/window.h" #include "ui/aura/window_observer.h" |