summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authorben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-12 22:10:51 +0000
committerben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-12 22:10:51 +0000
commit9b10d2a051ec36c4e7f012d31b8214221db16eaa (patch)
treeb6242231f0674978d51071f02f511c81370a022c /ui
parent178520e30cfa28c3e33dd24a1868a06332975de4 (diff)
downloadchromium_src-9b10d2a051ec36c4e7f012d31b8214221db16eaa.zip
chromium_src-9b10d2a051ec36c4e7f012d31b8214221db16eaa.tar.gz
chromium_src-9b10d2a051ec36c4e7f012d31b8214221db16eaa.tar.bz2
Move the concept of Activation to the Shell.
The Active Window is now stored in a property on the RootWindow. Classes wishing to observe changes to this can implement WindowObserver and attach to the RootWindow to be notified of changes in this property. We provide an ActivationClient interface in Aura for customers to use to set/get the active window, and deactivate a window. This is because setting the active window involves more than just changing the property, there is some additional book-keeping that must be done. The ActivationClient is stored in a property on the RootWindow. We also provide an ActivationDelegate interface in Aura that window owners can use to be notified of changes in activation state, and to specify whether or not a window can be activated. The ActivationDelegate should be stored on the relevant window in a property. I moved a lot of Activation-related functionality out of Aura, including all of the unit tests, now on ActivationController, and the associated WindowDelegate implementations which have now become a single TestActivationDelegate implementation. BUG=none TEST=unit tests Review URL: http://codereview.chromium.org/8894018 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@114095 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
-rw-r--r--ui/aura/aura.gyp6
-rw-r--r--ui/aura/client/activation_client.cc23
-rw-r--r--ui/aura/client/activation_client.h42
-rw-r--r--ui/aura/client/activation_delegate.cc24
-rw-r--r--ui/aura/client/activation_delegate.h43
-rw-r--r--ui/aura/client/aura_constants.cc15
-rw-r--r--ui/aura/client/aura_constants.h52
-rw-r--r--ui/aura/client/stacking_client.h8
-rw-r--r--ui/aura/demo/demo_main.cc3
-rw-r--r--ui/aura/root_window.cc96
-rw-r--r--ui/aura/root_window.h25
-rw-r--r--ui/aura/root_window_observer.h5
-rw-r--r--ui/aura/test/test_activation_client.cc59
-rw-r--r--ui/aura/test/test_activation_client.h44
-rw-r--r--ui/aura/test/test_stacking_client.cc15
-rw-r--r--ui/aura/test/test_stacking_client.h2
-rw-r--r--ui/aura/test/test_window_delegate.cc38
-rw-r--r--ui/aura/test/test_window_delegate.h30
-rw-r--r--ui/aura/window.cc21
-rw-r--r--ui/aura/window.h14
-rw-r--r--ui/aura/window_delegate.h12
-rw-r--r--ui/aura/window_unittest.cc146
-rw-r--r--ui/aura_shell/activation_controller.cc185
-rw-r--r--ui/aura_shell/activation_controller.h74
-rw-r--r--ui/aura_shell/activation_controller_unittest.cc281
-rw-r--r--ui/aura_shell/aura_shell.gyp6
-rw-r--r--ui/aura_shell/default_container_event_filter.cc4
-rw-r--r--ui/aura_shell/default_container_layout_manager.cc3
-rw-r--r--ui/aura_shell/examples/aura_shell_main.cc3
-rw-r--r--ui/aura_shell/modal_container_layout_manager.cc8
-rw-r--r--ui/aura_shell/modal_container_layout_manager_unittest.cc23
-rw-r--r--ui/aura_shell/root_window_event_filter.cc18
-rw-r--r--ui/aura_shell/root_window_event_filter.h5
-rw-r--r--ui/aura_shell/root_window_event_filter_unittest.cc125
-rw-r--r--ui/aura_shell/shadow_controller.cc4
-rw-r--r--ui/aura_shell/shell.cc3
-rw-r--r--ui/aura_shell/shell.h2
-rw-r--r--ui/aura_shell/stacking_controller.cc43
-rw-r--r--ui/aura_shell/stacking_controller.h7
-rw-r--r--ui/aura_shell/stacking_controller_unittest.cc59
-rw-r--r--ui/aura_shell/test/test_activation_delegate.cc53
-rw-r--r--ui/aura_shell/test/test_activation_delegate.h59
-rw-r--r--ui/aura_shell/window_util.cc25
-rw-r--r--ui/aura_shell/window_util.h13
-rw-r--r--ui/aura_shell/workspace/workspace.cc3
-rw-r--r--ui/aura_shell/workspace/workspace_manager_unittest.cc15
-rw-r--r--ui/aura_shell/workspace_controller.cc21
-rw-r--r--ui/aura_shell/workspace_controller.h10
-rw-r--r--ui/aura_shell/workspace_controller_unittest.cc18
-rw-r--r--ui/views/test/views_test_base.cc2
-rw-r--r--ui/views/test/views_test_base.h9
-rw-r--r--ui/views/widget/native_widget_aura.cc77
-rw-r--r--ui/views/widget/native_widget_aura.h14
53 files changed, 1231 insertions, 664 deletions
diff --git a/ui/aura/aura.gyp b/ui/aura/aura.gyp
index f6e03a6..9ac8248 100644
--- a/ui/aura/aura.gyp
+++ b/ui/aura/aura.gyp
@@ -25,6 +25,10 @@
'sources': [
'aura_switches.cc',
'aura_switches.h',
+ 'client/activation_client.cc',
+ 'client/activation_client.h',
+ 'client/activation_delegate.cc',
+ 'client/activation_delegate.h',
'client/aura_constants.cc',
'client/aura_constants.h',
'client/drag_drop_client.h',
@@ -71,6 +75,8 @@
'test/aura_test_base.h',
'test/event_generator.cc',
'test/event_generator.h',
+ 'test/test_activation_client.cc',
+ 'test/test_activation_client.h',
'test/test_event_filter.cc',
'test/test_event_filter.h',
'test/test_stacking_client.cc',
diff --git a/ui/aura/client/activation_client.cc b/ui/aura/client/activation_client.cc
new file mode 100644
index 0000000..8106ca2
--- /dev/null
+++ b/ui/aura/client/activation_client.cc
@@ -0,0 +1,23 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/aura/client/activation_client.h"
+
+#include "ui/aura/client/aura_constants.h"
+#include "ui/aura/root_window.h"
+
+namespace aura {
+
+// static
+void ActivationClient::SetActivationClient(ActivationClient* client) {
+ RootWindow::GetInstance()->SetProperty(kRootWindowActivationClient, client);
+}
+
+// static
+ActivationClient* ActivationClient::GetActivationClient() {
+ return reinterpret_cast<ActivationClient*>(
+ RootWindow::GetInstance()->GetProperty(kRootWindowActivationClient));
+}
+
+} // namespace aura
diff --git a/ui/aura/client/activation_client.h b/ui/aura/client/activation_client.h
new file mode 100644
index 0000000..547f9ab
--- /dev/null
+++ b/ui/aura/client/activation_client.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_AURA_CLIENT_ACTIVATION_CLIENT_H_
+#define UI_AURA_CLIENT_ACTIVATION_CLIENT_H_
+#pragma once
+
+#include "ui/aura/aura_export.h"
+
+namespace aura {
+
+class Window;
+
+// An interface implemented by an object that manages window activation.
+class AURA_EXPORT ActivationClient {
+ public:
+ // Sets/Gets the activation client on the RootWindow.
+ static void SetActivationClient(ActivationClient* client);
+ static ActivationClient* GetActivationClient();
+
+ // Activates |window|. If |window| is NULL, nothing happens.
+ virtual void ActivateWindow(Window* window) = 0;
+
+ // Deactivates |window|. What (if anything) is activated next is up to the
+ // client. If |window| is NULL, nothing happens.
+ virtual void DeactivateWindow(Window* window) = 0;
+
+ // Retrieves the active window, or NULL if there is none.
+ virtual aura::Window* GetActiveWindow() = 0;
+
+ // Returns true if |window| can be focused. To be focusable, |window| must
+ // exist inside an activatable window.
+ virtual bool CanFocusWindow(Window* window) const = 0;
+
+ protected:
+ virtual ~ActivationClient() {}
+};
+
+} // namespace aura
+
+#endif // UI_AURA_CLIENT_ACTIVATION_CLIENT_H_
diff --git a/ui/aura/client/activation_delegate.cc b/ui/aura/client/activation_delegate.cc
new file mode 100644
index 0000000..18688f0
--- /dev/null
+++ b/ui/aura/client/activation_delegate.cc
@@ -0,0 +1,24 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/aura/client/activation_delegate.h"
+
+#include "ui/aura/client/aura_constants.h"
+#include "ui/aura/window.h"
+
+namespace aura {
+
+// static
+void ActivationDelegate::SetActivationDelegate(Window* window,
+ ActivationDelegate* delegate) {
+ window->SetProperty(kActivationDelegateKey, delegate);
+}
+
+// static
+ActivationDelegate* ActivationDelegate::GetActivationDelegate(Window* window) {
+ return reinterpret_cast<ActivationDelegate*>(
+ window->GetProperty(kActivationDelegateKey));
+}
+
+} // namespace aura
diff --git a/ui/aura/client/activation_delegate.h b/ui/aura/client/activation_delegate.h
new file mode 100644
index 0000000..dd2933e
--- /dev/null
+++ b/ui/aura/client/activation_delegate.h
@@ -0,0 +1,43 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_AURA_CLIENT_ACTIVATION_DELEGATE_H_
+#define UI_AURA_CLIENT_ACTIVATION_DELEGATE_H_
+#pragma once
+
+#include "ui/aura/aura_export.h"
+
+namespace aura {
+
+class Event;
+class Window;
+
+// An interface implemented by an object that configures and responds to changes
+// to a window's activation state.
+class AURA_EXPORT ActivationDelegate {
+ public:
+ // Sets/Gets the ActivationDelegate on the Window. No ownership changes.
+ static void SetActivationDelegate(Window* window,
+ ActivationDelegate* delegate);
+ static ActivationDelegate* GetActivationDelegate(Window* window);
+
+ // Returns true if the window should be activated. |event| is either the mouse
+ // event supplied if the activation is the result of a mouse, or the touch
+ // event if the activation is the result of a touch, or NULL if activation is
+ // attempted for another reason.
+ virtual bool ShouldActivate(Event* event) = 0;
+
+ // Sent when the window is activated.
+ virtual void OnActivated() = 0;
+
+ // Sent when the window loses active status.
+ virtual void OnLostActive() = 0;
+
+ protected:
+ virtual ~ActivationDelegate() {}
+};
+
+} // namespace aura
+
+#endif // UI_AURA_CLIENT_ACTIVATION_DELEGATE_H_
diff --git a/ui/aura/client/aura_constants.cc b/ui/aura/client/aura_constants.cc
index 9536a1f..c1d0d6e 100644
--- a/ui/aura/client/aura_constants.cc
+++ b/ui/aura/client/aura_constants.cc
@@ -6,14 +6,19 @@
namespace aura {
+// Alphabetical sort.
+const char kActivationDelegateKey[] = "ActivationDelegate";
const char kAlwaysOnTopKey[] = "AlwaysOnTop";
-const char kRestoreBoundsKey[] = "RestoreBounds";
-const char kShowStateKey[] = "ShowState";
-const char kTooltipTextKey[] = "TooltipText";
+const char kDragDropDelegateKey[] = "DragDropDelegate";
const char kModalKey[] = "Modal";
-const char kShadowTypeKey[] = "ShadowType";
+const char kRestoreBoundsKey[] = "RestoreBounds";
const char kRootWindowDragDropClientKey[] = "RootWindowDragDropClient";
-const char kDragDropDelegateKey[] = "DragDropDelegate";
const char kRootWindowTooltipClientKey[] = "RootWindowTooltipClient";
+const char kRootWindowActiveWindow[] = "RootWindowActiveWindow";
+const char kRootWindowActivationClient[] = "RootWindowActivationClient";
+const char kShadowTypeKey[] = "ShadowType";
+const char kShowStateKey[] = "ShowState";
+const char kTooltipTextKey[] = "TooltipText";
+// Alphabetical sort.
} // namespace aura
diff --git a/ui/aura/client/aura_constants.h b/ui/aura/client/aura_constants.h
index c756396..f5f2920 100644
--- a/ui/aura/client/aura_constants.h
+++ b/ui/aura/client/aura_constants.h
@@ -9,41 +9,57 @@
#include "ui/aura/aura_export.h"
namespace aura {
-// Window property keys that are shared between aura_shell and chrome/views.
+
+// Alphabetical sort.
+
+// A property key to store the activation delegate for a window. The type of the
+// value is |aura::ActivationDelegate*|.
+AURA_EXPORT extern const char kActivationDelegateKey[];
// A property key to store always-on-top flag. The type of the value is boolean.
AURA_EXPORT extern const char kAlwaysOnTopKey[];
+// A property key to store the drag and drop delegate for a window. The type of
+// the value is |aura::WindowDragDropDelegate*|.
+AURA_EXPORT extern const char kDragDropDelegateKey[];
+
+// A property key to store the boolean property of window modality.
+AURA_EXPORT extern const char kModalKey[];
+
// A property key to store the restore bounds for a window. The type
// of the value is |gfx::Rect*|.
AURA_EXPORT extern const char kRestoreBoundsKey[];
-// A property key to store ui::WindowShowState for a window.
-// See ui/base/ui_base_types.h for its definition.
-AURA_EXPORT extern const char kShowStateKey[];
+// A property key to store the drag and drop client for the root window. The
+// type of the value is |aura::DragDropClient*|.
+AURA_EXPORT extern const char kRootWindowDragDropClientKey[];
-// A property key to store tooltip text for a window. The type of the value
-// is |string16*|.
-AURA_EXPORT extern const char kTooltipTextKey[];
+// A property key to store the tooltip client for the root window. The type of
+// the value is |aura::TooltipClient*|.
+AURA_EXPORT extern const char kRootWindowTooltipClientKey[];
-// A property key to store the boolean property of window modality.
-AURA_EXPORT extern const char kModalKey[];
+// A property key to store what the client defines as the active window on the
+// RootWindow. The type of the value is |aura::Window*|.
+AURA_EXPORT extern const char kRootWindowActiveWindow[];
+
+// A property key to store a client that handles window activation. The type of
+// the value is |aura::ActivationClient*|.
+AURA_EXPORT extern const char kRootWindowActivationClient[];
// A property key for a value from aura::ShadowType describing the drop shadow
// that should be displayed under the window. If unset, no shadow is displayed.
AURA_EXPORT extern const char kShadowTypeKey[];
-// A property key to store the drag and drop client for the root window. The
-// type of the value is |aura::DragDropClient*|.
-AURA_EXPORT extern const char kRootWindowDragDropClientKey[];
+// A property key to store ui::WindowShowState for a window.
+// See ui/base/ui_base_types.h for its definition.
+AURA_EXPORT extern const char kShowStateKey[];
-// A property key to store the drag and drop delegate for a window. The type of
-// the value is |aura::WindowDragDropDelegate*|.
-AURA_EXPORT extern const char kDragDropDelegateKey[];
+// A property key to store tooltip text for a window. The type of the value
+// is |string16*|.
+AURA_EXPORT extern const char kTooltipTextKey[];
+
+// Alphabetical sort.
-// A property key to store the tooltip client for the root window. The type of
-// the value is |aura::TooltipClient*|.
-AURA_EXPORT extern const char kRootWindowTooltipClientKey[];
} // namespace aura
#endif // UI_AURA_CLIENT_AURA_CONSTANTS_H_
diff --git a/ui/aura/client/stacking_client.h b/ui/aura/client/stacking_client.h
index 26d137b..6e89636 100644
--- a/ui/aura/client/stacking_client.h
+++ b/ui/aura/client/stacking_client.h
@@ -21,14 +21,6 @@ class AURA_EXPORT StackingClient {
// an opportunity to inspect the window and add it to a default parent window
// of its choosing.
virtual void AddChildToDefaultParent(Window* window) = 0;
-
- // Returns true if |window| can be activated or deactivated.
- // A window manager typically defines some notion of "top level window" that
- // supports activation/deactivation.
- virtual bool CanActivateWindow(Window* window) const = 0;
-
- // Returns the window that should be activated other than |ignore|.
- virtual Window* GetTopmostWindowToActivate(Window* ignore) const = 0;
};
} // namespace aura
diff --git a/ui/aura/demo/demo_main.cc b/ui/aura/demo/demo_main.cc
index 76b87bd..817ec7f 100644
--- a/ui/aura/demo/demo_main.cc
+++ b/ui/aura/demo/demo_main.cc
@@ -54,9 +54,6 @@ class DemoWindowDelegate : public aura::WindowDelegate {
return ui::TOUCH_STATUS_END;
}
virtual bool CanFocus() OVERRIDE { return true; }
- virtual bool ShouldActivate(aura::Event* event) OVERRIDE { return true; }
- virtual void OnActivated() OVERRIDE {}
- virtual void OnLostActive() OVERRIDE {}
virtual void OnCaptureLost() OVERRIDE {}
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
canvas->GetSkCanvas()->drawColor(color_, SkXfermode::kSrc_Mode);
diff --git a/ui/aura/root_window.cc b/ui/aura/root_window.cc
index c0eb9b8..7396ad6 100644
--- a/ui/aura/root_window.cc
+++ b/ui/aura/root_window.cc
@@ -14,6 +14,7 @@
#include "base/string_number_conversions.h"
#include "base/string_split.h"
#include "ui/aura/aura_switches.h"
+#include "ui/aura/client/activation_client.h"
#include "ui/aura/client/drag_drop_client.h"
#include "ui/aura/client/stacking_client.h"
#include "ui/aura/client/tooltip_client.h"
@@ -69,20 +70,6 @@ class DefaultStackingClient : public StackingClient {
virtual void AddChildToDefaultParent(Window* window) OVERRIDE {
root_window_->AddChild(window);
}
- virtual bool CanActivateWindow(Window* window) const OVERRIDE {
- return window->parent() == root_window_;
- }
- virtual Window* GetTopmostWindowToActivate(Window* ignore) const OVERRIDE {
- Window::Windows::const_reverse_iterator i;
- for (i = root_window_->children().rbegin();
- i != root_window_->children().rend();
- ++i) {
- if (*i == ignore)
- continue;
- return *i;
- }
- return NULL;
- }
RootWindow* root_window_;
@@ -247,55 +234,6 @@ void RootWindow::OnNativeScreenResized(const gfx::Size& size) {
SetHostSize(size);
}
-void RootWindow::SetActiveWindow(Window* window, Window* to_focus) {
- if (!window)
- return;
- // The stacking client may impose rules on what window configurations can be
- // activated or deactivated.
- if (!stacking_client_->CanActivateWindow(window))
- return;
- // The window may not be activate-able.
- if (!window->CanActivate())
- return;
- // Nothing may actually have changed.
- if (active_window_ == window)
- return;
-
- Window* old_active = active_window_;
- active_window_ = window;
- // Invoke OnLostActive after we've changed the active window. That way if the
- // delegate queries for active state it doesn't think the window is still
- // active.
- if (old_active && old_active->delegate())
- old_active->delegate()->OnLostActive();
- if (active_window_) {
- active_window_->parent()->StackChildAtTop(active_window_);
- if (active_window_->delegate())
- active_window_->delegate()->OnActivated();
- active_window_->GetFocusManager()->SetFocusedWindow(
- to_focus ? to_focus : active_window_);
- }
- FOR_EACH_OBSERVER(RootWindowObserver, observers_,
- OnActiveWindowChanged(active_window_));
-}
-
-void RootWindow::ActivateTopmostWindow() {
- SetActiveWindow(stacking_client_->GetTopmostWindowToActivate(NULL), NULL);
-}
-
-void RootWindow::Deactivate(Window* window) {
- // The stacking client may impose rules on what window configurations can be
- // activated or deactivated.
- if (!window || !stacking_client_->CanActivateWindow(window))
- return;
- if (active_window_ != window)
- return;
-
- Window* to_activate = stacking_client_->GetTopmostWindowToActivate(window);
- if (to_activate)
- SetActiveWindow(to_activate, NULL);
-}
-
void RootWindow::WindowInitialized(Window* window) {
FOR_EACH_OBSERVER(RootWindowObserver, observers_,
OnWindowInitialized(window));
@@ -317,25 +255,17 @@ void RootWindow::WindowDestroying(Window* window) {
capture_window_ = NULL;
if (touch_event_handler_ == window)
touch_event_handler_ = NULL;
-
- if (in_destructor_ || window != active_window_)
- return;
-
- // Reset active_window_ before invoking SetActiveWindow so that we don't
- // attempt to notify it while running its destructor.
- active_window_ = NULL;
- SetActiveWindow(stacking_client_->GetTopmostWindowToActivate(window), NULL);
}
MessageLoop::Dispatcher* RootWindow::GetDispatcher() {
return host_.get();
}
-void RootWindow::AddObserver(RootWindowObserver* observer) {
+void RootWindow::AddRootWindowObserver(RootWindowObserver* observer) {
observers_.AddObserver(observer);
}
-void RootWindow::RemoveObserver(RootWindowObserver* observer) {
+void RootWindow::RemoveRootWindowObserver(RootWindowObserver* observer) {
observers_.RemoveObserver(observer);
}
@@ -406,10 +336,8 @@ RootWindow::RootWindow()
ALLOW_THIS_IN_INITIALIZER_LIST(
stacking_client_(new DefaultStackingClient(this))),
ALLOW_THIS_IN_INITIALIZER_LIST(schedule_paint_factory_(this)),
- active_window_(NULL),
mouse_button_flags_(0),
last_cursor_(kCursorNull),
- in_destructor_(false),
screen_(new ScreenAura),
capture_window_(NULL),
mouse_pressed_handler_(NULL),
@@ -434,7 +362,6 @@ RootWindow::RootWindow()
}
RootWindow::~RootWindow() {
- in_destructor_ = true;
// Make sure to destroy the compositor before terminating so that state is
// cleared and we don't hit asserts.
compositor_ = NULL;
@@ -571,15 +498,28 @@ void RootWindow::OnLayerAnimationAborted(
}
void RootWindow::SetFocusedWindow(Window* focused_window) {
- if (focused_window == focused_window_ ||
- (focused_window && !focused_window->CanFocus())) {
+ 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 && ActivationClient::GetActivationClient() &&
+ !ActivationClient::GetActivationClient()->CanFocusWindow(
+ focused_window)) {
return;
}
+
if (focused_window_ && focused_window_->delegate())
focused_window_->delegate()->OnBlur();
focused_window_ = focused_window;
if (focused_window_ && focused_window_->delegate())
focused_window_->delegate()->OnFocus();
+ if (focused_window_) {
+ FOR_EACH_OBSERVER(RootWindowObserver, observers_,
+ OnWindowFocused(focused_window_));
+ }
}
Window* RootWindow::GetFocusedWindow() {
diff --git a/ui/aura/root_window.h b/ui/aura/root_window.h
index ddefbe7..52640dc 100644
--- a/ui/aura/root_window.h
+++ b/ui/aura/root_window.h
@@ -57,7 +57,6 @@ class AURA_EXPORT RootWindow : public ui::CompositorDelegate,
gfx::Point last_mouse_location() const { return last_mouse_location_; }
gfx::NativeCursor last_cursor() const { return last_cursor_; }
StackingClient* stacking_client() { return stacking_client_.get(); }
- Window* active_window() { return active_window_; }
Window* mouse_pressed_handler() { return mouse_pressed_handler_; }
Window* capture_window() { return capture_window_; }
ScreenAura* screen() { return screen_; }
@@ -95,20 +94,6 @@ class AURA_EXPORT RootWindow : public ui::CompositorDelegate,
// Called when the native screen's resolution changes.
void OnNativeScreenResized(const gfx::Size& size);
- // Sets the active window to |window| and the focused window to |to_focus|.
- // If |to_focus| is NULL, |window| is focused. Does nothing if |window| is
- // NULL.
- void SetActiveWindow(Window* window, Window* to_focus);
-
- // Activates the topmost window. Does nothing if the topmost window is already
- // active.
- void ActivateTopmostWindow();
-
- // Deactivates |window| and activates the topmost window. Does nothing if
- // |window| is not a topmost window, or there are no other suitable windows to
- // activate.
- void Deactivate(Window* window);
-
// Invoked when |window| is initialized.
void WindowInitialized(Window* window);
@@ -122,8 +107,8 @@ class AURA_EXPORT RootWindow : public ui::CompositorDelegate,
MessageLoop::Dispatcher* GetDispatcher();
// Add/remove observer.
- void AddObserver(RootWindowObserver* observer);
- void RemoveObserver(RootWindowObserver* observer);
+ void AddRootWindowObserver(RootWindowObserver* observer);
+ void RemoveRootWindowObserver(RootWindowObserver* observer);
// Are any mouse buttons currently down?
bool IsMouseButtonDown() const;
@@ -208,8 +193,6 @@ class AURA_EXPORT RootWindow : public ui::CompositorDelegate,
// Used to schedule painting.
base::WeakPtrFactory<RootWindow> schedule_paint_factory_;
- Window* active_window_;
-
// Last location seen in a mouse event.
gfx::Point last_mouse_location_;
@@ -219,10 +202,6 @@ class AURA_EXPORT RootWindow : public ui::CompositorDelegate,
// Last cursor set. Used for testing.
gfx::NativeCursor last_cursor_;
- // Are we in the process of being destroyed? Used to avoid processing during
- // destruction.
- bool in_destructor_;
-
ObserverList<RootWindowObserver> observers_;
ScreenAura* screen_;
diff --git a/ui/aura/root_window_observer.h b/ui/aura/root_window_observer.h
index 41417f2..8cc48e6 100644
--- a/ui/aura/root_window_observer.h
+++ b/ui/aura/root_window_observer.h
@@ -24,9 +24,8 @@ class AURA_EXPORT RootWindowObserver {
// Invoked when a new window is initialized.
virtual void OnWindowInitialized(Window* window) {}
- // Invoked when the active window is changed. |active| may be NULL if there is
- // not active window.
- virtual void OnActiveWindowChanged(Window* active) {}
+ // Invoked when a window is focused.
+ virtual void OnWindowFocused(Window* window) {}
protected:
virtual ~RootWindowObserver() {}
diff --git a/ui/aura/test/test_activation_client.cc b/ui/aura/test/test_activation_client.cc
new file mode 100644
index 0000000..6f32ea7
--- /dev/null
+++ b/ui/aura/test/test_activation_client.cc
@@ -0,0 +1,59 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/aura/test/test_activation_client.h"
+
+#include "ui/aura/window.h"
+
+namespace aura {
+namespace test {
+
+////////////////////////////////////////////////////////////////////////////////
+// TestActivationClient, public:
+
+TestActivationClient::TestActivationClient() : active_window_(NULL) {
+ ActivationClient::SetActivationClient(this);
+}
+
+TestActivationClient::~TestActivationClient() {
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// TestActivationClient, ActivationClient implementation:
+
+void TestActivationClient::ActivateWindow(Window* window) {
+ if (active_window_)
+ active_window_->RemoveObserver(this);
+ active_window_ = window;
+ active_window_->AddObserver(this);
+}
+
+void TestActivationClient::DeactivateWindow(Window* window) {
+ if (window == active_window_) {
+ if (active_window_)
+ active_window_->RemoveObserver(this);
+ active_window_ = NULL;
+ }
+}
+
+Window* TestActivationClient::GetActiveWindow() {
+ return active_window_;
+}
+
+bool TestActivationClient::CanFocusWindow(Window* window) const {
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// TestActivationClient, WindowObserver implementation:
+
+void TestActivationClient::OnWindowDestroyed(Window* window) {
+ if (window == active_window_) {
+ window->RemoveObserver(this);
+ active_window_ = NULL;
+ }
+}
+
+} // namespace test
+} // namespace aura
diff --git a/ui/aura/test/test_activation_client.h b/ui/aura/test/test_activation_client.h
new file mode 100644
index 0000000..22d56e5
--- /dev/null
+++ b/ui/aura/test/test_activation_client.h
@@ -0,0 +1,44 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_AURA_TEST_TEST_ACTIVATION_CLIENT_H_
+#define UI_AURA_TEST_TEST_ACTIVATION_CLIENT_H_
+#pragma once
+
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "ui/aura/client/activation_client.h"
+#include "ui/aura/window_observer.h"
+
+namespace aura {
+namespace test {
+
+class TestActivationClient : public ActivationClient, public WindowObserver {
+ public:
+ TestActivationClient();
+ virtual ~TestActivationClient();
+
+ // Overridden from ActivationClient:
+ virtual void ActivateWindow(Window* window) OVERRIDE;
+ virtual void DeactivateWindow(Window* window) OVERRIDE;
+ virtual Window* GetActiveWindow() OVERRIDE;
+ virtual bool CanFocusWindow(Window* window) const OVERRIDE;
+
+ // Overridden from WindowObserver:
+ virtual void OnWindowDestroyed(Window* window) OVERRIDE;
+
+ private:
+ // This class explicitly does NOT store the active window in a window property
+ // to make sure that storing the active window in a property is not treated as
+ // part of the aura API. Assumptions to that end will cause tests that use
+ // this client to fail.
+ Window* active_window_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestActivationClient);
+};
+
+} // namespace test
+} // namespace aura
+
+#endif // UI_AURA_TEST_TEST_ACTIVATION_CLIENT_H_ \ No newline at end of file
diff --git a/ui/aura/test/test_stacking_client.cc b/ui/aura/test/test_stacking_client.cc
index 4c3ce31..18048f3 100644
--- a/ui/aura/test/test_stacking_client.cc
+++ b/ui/aura/test/test_stacking_client.cc
@@ -26,20 +26,5 @@ void TestStackingClient::AddChildToDefaultParent(Window* window) {
default_container_->AddChild(window);
}
-bool TestStackingClient::CanActivateWindow(Window* window) const {
- return window->parent() == default_container_;
-}
-
-Window* TestStackingClient::GetTopmostWindowToActivate(Window* ignore) const {
- for (aura::Window::Windows::const_reverse_iterator i =
- default_container_->children().rbegin();
- i != default_container_->children().rend();
- ++i) {
- if (*i != ignore && (*i)->CanActivate())
- return *i;
- }
- return NULL;
-}
-
} // namespace test
} // namespace aura
diff --git a/ui/aura/test/test_stacking_client.h b/ui/aura/test/test_stacking_client.h
index 3ea0ba5..73d9382 100644
--- a/ui/aura/test/test_stacking_client.h
+++ b/ui/aura/test/test_stacking_client.h
@@ -29,8 +29,6 @@ class TestStackingClient : public StackingClient {
private:
// Overridden from StackingClient:
virtual void AddChildToDefaultParent(Window* window) OVERRIDE;
- virtual bool CanActivateWindow(Window* window) const OVERRIDE;
- virtual Window* GetTopmostWindowToActivate(Window* ignore) const OVERRIDE;
scoped_ptr<Window> default_container_;
diff --git a/ui/aura/test/test_window_delegate.cc b/ui/aura/test/test_window_delegate.cc
index 4a4f778..661e168 100644
--- a/ui/aura/test/test_window_delegate.cc
+++ b/ui/aura/test/test_window_delegate.cc
@@ -60,16 +60,6 @@ bool TestWindowDelegate::CanFocus() {
return true;
}
-bool TestWindowDelegate::ShouldActivate(Event* event) {
- return true;
-}
-
-void TestWindowDelegate::OnActivated() {
-}
-
-void TestWindowDelegate::OnLostActive() {
-}
-
void TestWindowDelegate::OnCaptureLost() {
}
@@ -107,33 +97,5 @@ void ColorTestWindowDelegate::OnPaint(gfx::Canvas* canvas) {
canvas->GetSkCanvas()->drawColor(color_, SkXfermode::kSrc_Mode);
}
-////////////////////////////////////////////////////////////////////////////////
-// ActivateWindowDelegate
-
-ActivateWindowDelegate::ActivateWindowDelegate()
- : activate_(true),
- activated_count_(0),
- lost_active_count_(0),
- should_activate_count_(0) {
-}
-
-ActivateWindowDelegate::ActivateWindowDelegate(bool activate)
- : activate_(activate),
- activated_count_(0),
- lost_active_count_(0),
- should_activate_count_(0) {
-}
-
-bool ActivateWindowDelegate::ShouldActivate(Event* event) {
- should_activate_count_++;
- return activate_;
-}
-void ActivateWindowDelegate::OnActivated() {
- activated_count_++;
-}
-void ActivateWindowDelegate::OnLostActive() {
- lost_active_count_++;
-}
-
} // namespace test
} // namespace aura
diff --git a/ui/aura/test/test_window_delegate.h b/ui/aura/test/test_window_delegate.h
index 08f1d6f..12b241b 100644
--- a/ui/aura/test/test_window_delegate.h
+++ b/ui/aura/test/test_window_delegate.h
@@ -31,9 +31,6 @@ class TestWindowDelegate : public WindowDelegate {
virtual bool OnMouseEvent(MouseEvent* event) OVERRIDE;
virtual ui::TouchStatus OnTouchEvent(TouchEvent* event) OVERRIDE;
virtual bool CanFocus() OVERRIDE;
- virtual bool ShouldActivate(Event* event) OVERRIDE;
- virtual void OnActivated() OVERRIDE;
- virtual void OnLostActive() OVERRIDE;
virtual void OnCaptureLost() OVERRIDE;
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
virtual void OnWindowDestroying() OVERRIDE;
@@ -65,33 +62,6 @@ class ColorTestWindowDelegate : public TestWindowDelegate {
DISALLOW_COPY_AND_ASSIGN(ColorTestWindowDelegate);
};
-class ActivateWindowDelegate : public TestWindowDelegate {
- public:
- ActivateWindowDelegate();
- explicit ActivateWindowDelegate(bool activate);
-
- void set_activate(bool v) { activate_ = v; }
- int activated_count() const { return activated_count_; }
- int lost_active_count() const { return lost_active_count_; }
- int should_activate_count() const { return should_activate_count_; }
- void Clear() {
- activated_count_ = lost_active_count_ = should_activate_count_ = 0;
- }
-
- // Overridden from TestWindowDelegate:
- virtual bool ShouldActivate(Event* event) OVERRIDE;
- virtual void OnActivated() OVERRIDE;
- virtual void OnLostActive() OVERRIDE;
-
- private:
- bool activate_;
- int activated_count_;
- int lost_active_count_;
- int should_activate_count_;
-
- DISALLOW_COPY_AND_ASSIGN(ActivateWindowDelegate);
-};
-
} // namespace test
} // namespace aura
diff --git a/ui/aura/window.cc b/ui/aura/window.cc
index 74721fa..8a10667 100644
--- a/ui/aura/window.cc
+++ b/ui/aura/window.cc
@@ -103,10 +103,6 @@ void Window::Show() {
void Window::Hide() {
SetVisible(false);
ReleaseCapture();
- if (RootWindow::GetInstance()->active_window() == this ||
- !RootWindow::GetInstance()->active_window()) {
- RootWindow::GetInstance()->ActivateTopmostWindow();
- }
}
bool Window::IsVisible() const {
@@ -121,19 +117,6 @@ gfx::Rect Window::GetScreenBounds() const {
return gfx::Rect(origin, bounds().size());
}
-void Window::Activate() {
- // If we support minimization need to ensure this restores the window first.
- aura::RootWindow::GetInstance()->SetActiveWindow(this, this);
-}
-
-void Window::Deactivate() {
- aura::RootWindow::GetInstance()->Deactivate(this);
-}
-
-bool Window::IsActive() const {
- return aura::RootWindow::GetInstance()->active_window() == this;
-}
-
void Window::SetTransform(const ui::Transform& transform) {
layer()->SetTransform(transform);
}
@@ -219,10 +202,6 @@ void Window::StackChildAbove(Window* child, Window* other) {
child->OnStackingChanged();
}
-bool Window::CanActivate() const {
- return IsVisible() && (!delegate_ || delegate_->ShouldActivate(NULL));
-}
-
void Window::AddChild(Window* child) {
DCHECK(std::find(children_.begin(), children_.end(), child) ==
children_.end());
diff --git a/ui/aura/window.h b/ui/aura/window.h
index 2c77d39..dcd115d 100644
--- a/ui/aura/window.h
+++ b/ui/aura/window.h
@@ -92,14 +92,6 @@ class AURA_EXPORT Window : public ui::LayerDelegate {
// Returns the window's bounds in screen coordinates.
gfx::Rect GetScreenBounds() const;
- // Activates this window. Only top level windows can be activated. Requests
- // to activate a non-top level window are ignored.
- void Activate();
-
- // Deactivates this window. Only top level windows can be
- // deactivated. Requests to deactivate a non-top level window are ignored.
- void Deactivate();
-
// Returns true if this window is active.
bool IsActive() const;
@@ -135,9 +127,6 @@ class AURA_EXPORT Window : public ui::LayerDelegate {
// |other|.
void StackChildAbove(Window* child, Window* other);
- // Returns true if this window can be activated.
- bool CanActivate() const;
-
// Tree operations.
// TODO(beng): Child windows are currently not owned by the hierarchy. We
// should change this.
@@ -248,7 +237,8 @@ class AURA_EXPORT Window : public ui::LayerDelegate {
// Sets the window property |value| for given |name|. Setting NULL or 0
// removes the property. It uses |ui::ViewProp| to store the property.
- // Please see the description of |prop_map_| for more details.
+ // Please see the description of |prop_map_| for more details. The caller is
+ // responsible for the lifetime of any object set as a property on the Window.
void SetProperty(const char* name, void* value);
void SetIntProperty(const char* name, int value);
diff --git a/ui/aura/window_delegate.h b/ui/aura/window_delegate.h
index f865511..25070c2 100644
--- a/ui/aura/window_delegate.h
+++ b/ui/aura/window_delegate.h
@@ -55,18 +55,6 @@ class AURA_EXPORT WindowDelegate {
// Returns true of the window can be focused.
virtual bool CanFocus() = 0;
- // Returns true if the window should be activated. |event| is either the mouse
- // event supplied if the activation is the result of a mouse, or the touch
- // event if the activation is the result of a touch, or NULL if activation is
- // attempted for another reason.
- virtual bool ShouldActivate(Event* event) = 0;
-
- // Sent when the window is activated.
- virtual void OnActivated() = 0;
-
- // Sent when the window loses active status.
- virtual void OnLostActive() = 0;
-
// Invoked when mouse capture is lost on the window.
virtual void OnCaptureLost() = 0;
diff --git a/ui/aura/window_unittest.cc b/ui/aura/window_unittest.cc
index d812446..ccd9fe8 100644
--- a/ui/aura/window_unittest.cc
+++ b/ui/aura/window_unittest.cc
@@ -544,70 +544,6 @@ TEST_F(WindowTest, MouseEnterExit) {
EXPECT_FALSE(d2.exited());
}
-namespace {
-
-class ActiveWindowDelegate : public TestWindowDelegate {
- public:
- ActiveWindowDelegate() : window_(NULL), was_active_(false), hit_count_(0) {
- }
-
- void set_window(Window* window) { window_ = window; }
-
- // Number of times OnLostActive has been invoked.
- int hit_count() const { return hit_count_; }
-
- // Was the window active from the first call to OnLostActive?
- bool was_active() const { return was_active_; }
-
- virtual void OnLostActive() OVERRIDE {
- if (hit_count_++ == 0)
- was_active_ = window_->IsActive();
- }
-
- private:
- Window* window_;
-
- // See description above getters for details on these.
- bool was_active_;
- int hit_count_;
-
- DISALLOW_COPY_AND_ASSIGN(ActiveWindowDelegate);
-};
-
-} // namespace
-
-// Verifies that when WindowDelegate::OnLostActive is invoked the window is not
-// active.
-TEST_F(WindowTest, NotActiveInLostActive) {
- RootWindow* root_window = RootWindow::GetInstance();
-
- ActiveWindowDelegate d1;
- scoped_ptr<Window> w1(
- CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50), NULL));
- d1.set_window(w1.get());
- scoped_ptr<Window> w2(
- CreateTestWindowWithDelegate(NULL, 1, gfx::Rect(10, 10, 50, 50), NULL));
-
- // Activate w1.
- root_window->SetActiveWindow(w1.get(), NULL);
- EXPECT_EQ(w1.get(), root_window->active_window());
-
- // Should not have gotten a OnLostActive yet.
- EXPECT_EQ(0, d1.hit_count());
-
- // SetActiveWindow(NULL) should not change the active window.
- root_window->SetActiveWindow(NULL, NULL);
- EXPECT_TRUE(root_window->active_window() == w1.get());
-
- // Now activate another window.
- root_window->SetActiveWindow(w2.get(), NULL);
-
- // Should have gotten OnLostActive and w1 should not have been active at that
- // time.
- EXPECT_EQ(1, d1.hit_count());
- EXPECT_FALSE(d1.was_active());
-}
-
// Creates a window with a delegate (w111) that can handle events at a lower
// z-index than a window without a delegate (w12). w12 is sized to fill the
// entire bounds of the container. This test verifies that
@@ -775,37 +711,6 @@ TEST_F(WindowTest, IgnoreEventsTest) {
EXPECT_EQ(w11.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160)));
}
-// Various assertions for activating/deactivating.
-TEST_F(WindowTest, Deactivate) {
- TestWindowDelegate d1;
- TestWindowDelegate d2;
- scoped_ptr<Window> w1(
- CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(), NULL));
- scoped_ptr<Window> w2(
- CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(), NULL));
- Window* parent = w1->parent();
- parent->Show();
- ASSERT_TRUE(parent);
- ASSERT_EQ(2u, parent->children().size());
- // Activate w2 and make sure it's active and frontmost.
- w2->Activate();
- EXPECT_TRUE(w2->IsActive());
- EXPECT_FALSE(w1->IsActive());
- EXPECT_EQ(w2.get(), parent->children()[1]);
-
- // Activate w1 and make sure it's active and frontmost.
- w1->Activate();
- EXPECT_TRUE(w1->IsActive());
- EXPECT_FALSE(w2->IsActive());
- EXPECT_EQ(w1.get(), parent->children()[1]);
-
- // Deactivate w1 and make sure w2 becomes active and frontmost.
- w1->Deactivate();
- EXPECT_FALSE(w1->IsActive());
- EXPECT_TRUE(w2->IsActive());
- EXPECT_EQ(w2.get(), parent->children()[1]);
-}
-
// Tests transformation on the root window.
TEST_F(WindowTest, Transform) {
RootWindow* root_window = RootWindow::GetInstance();
@@ -1121,56 +1026,5 @@ TEST_F(WindowObserverTest, PropertyChanged) {
EXPECT_EQ("name= old=0 new=0", PropertyChangeInfoAndClear());
}
-class RootWindowObserverTest : public WindowTest,
- public RootWindowObserver {
- public:
- RootWindowObserverTest() : active_(NULL) {
- }
-
- virtual ~RootWindowObserverTest() {}
-
- Window* active() const { return active_; }
-
- void Reset() {
- active_ = NULL;
- }
-
- private:
- virtual void SetUp() OVERRIDE {
- WindowTest::SetUp();
- RootWindow::GetInstance()->AddObserver(this);
- }
-
- virtual void TearDown() OVERRIDE {
- RootWindow::GetInstance()->RemoveObserver(this);
- WindowTest::TearDown();
- }
-
- virtual void OnActiveWindowChanged(Window* active) OVERRIDE {
- active_ = active;
- }
-
- Window* active_;
-
- DISALLOW_COPY_AND_ASSIGN(RootWindowObserverTest);
-};
-
-TEST_F(RootWindowObserverTest, WindowActivationObserve) {
- scoped_ptr<Window> w1(CreateTestWindowWithId(1, NULL));
- scoped_ptr<Window> w2(CreateTestWindowWithId(2, NULL));
- scoped_ptr<Window> w3(CreateTestWindowWithId(3, w1.get()));
-
- EXPECT_EQ(NULL, active());
-
- w2->Activate();
- EXPECT_EQ(w2.get(), active());
-
- w3->Activate();
- EXPECT_EQ(w2.get(), active());
-
- w1->Activate();
- EXPECT_EQ(w1.get(), active());
-}
-
} // namespace test
} // namespace aura
diff --git a/ui/aura_shell/activation_controller.cc b/ui/aura_shell/activation_controller.cc
new file mode 100644
index 0000000..dfa1b00
--- /dev/null
+++ b/ui/aura_shell/activation_controller.cc
@@ -0,0 +1,185 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/aura_shell/activation_controller.h"
+
+#include "base/auto_reset.h"
+#include "ui/aura/client/activation_delegate.h"
+#include "ui/aura/client/aura_constants.h"
+#include "ui/aura/root_window.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_delegate.h"
+#include "ui/aura_shell/shell.h"
+#include "ui/aura_shell/shell_window_ids.h"
+#include "ui/aura_shell/window_util.h"
+
+namespace aura_shell {
+namespace internal {
+namespace {
+
+aura::Window* GetContainer(int id) {
+ return Shell::GetInstance()->GetContainer(id);
+}
+
+// Returns true if children of |window| can be activated.
+bool SupportsChildActivation(aura::Window* window) {
+ return window->id() == kShellWindowId_DefaultContainer ||
+ window->id() == kShellWindowId_AlwaysOnTopContainer ||
+ window->id() == kShellWindowId_ModalContainer ||
+ window->id() == kShellWindowId_LockModalContainer;
+}
+
+// Returns true if |window| can be activated or deactivated.
+// A window manager typically defines some notion of "top level window" that
+// supports activation/deactivation.
+bool CanActivateWindow(aura::Window* window) {
+ return window &&
+ window->IsVisible() &&
+ (!aura::ActivationDelegate::GetActivationDelegate(window) ||
+ aura::ActivationDelegate::GetActivationDelegate(window)->
+ ShouldActivate(NULL)) &&
+ SupportsChildActivation(window->parent());
+}
+
+} // namespace
+
+////////////////////////////////////////////////////////////////////////////////
+// ActivationController, public:
+
+ActivationController::ActivationController()
+ : updating_activation_(false),
+ default_container_for_test_(NULL) {
+ aura::ActivationClient::SetActivationClient(this);
+ aura::RootWindow::GetInstance()->AddRootWindowObserver(this);
+}
+
+ActivationController::~ActivationController() {
+ aura::RootWindow::GetInstance()->RemoveRootWindowObserver(this);
+}
+
+// static
+aura::Window* ActivationController::GetActivatableWindow(aura::Window* window) {
+ aura::Window* parent = window->parent();
+ aura::Window* child = window;
+ while (parent) {
+ if (SupportsChildActivation(parent))
+ return child;
+ // If |child| isn't activatable, but has transient parent, trace
+ // that path instead.
+ if (child->transient_parent())
+ return GetActivatableWindow(child->transient_parent());
+ parent = parent->parent();
+ child = child->parent();
+ }
+ return NULL;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// StackingController, aura::ActivationClient implementation:
+
+void ActivationController::ActivateWindow(aura::Window* window) {
+ // Prevent recursion when called from focus.
+ if (updating_activation_)
+ return;
+
+ AutoReset<bool> in_activate_window(&updating_activation_, true);
+ if (!window)
+ return;
+ // Nothing may actually have changed.
+ aura::Window* old_active = GetActiveWindow();
+ if (old_active == window)
+ return;
+ // The stacking client may impose rules on what window configurations can be
+ // activated or deactivated.
+ if (!CanActivateWindow(window))
+ return;
+
+ if (!window->Contains(window->GetFocusManager()->GetFocusedWindow()))
+ window->GetFocusManager()->SetFocusedWindow(window);
+ aura::RootWindow::GetInstance()->SetProperty(aura::kRootWindowActiveWindow,
+ 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.
+ if (old_active && aura::ActivationDelegate::GetActivationDelegate(old_active))
+ aura::ActivationDelegate::GetActivationDelegate(old_active)->OnLostActive();
+ if (window) {
+ window->parent()->StackChildAtTop(window);
+ if (aura::ActivationDelegate::GetActivationDelegate(window))
+ aura::ActivationDelegate::GetActivationDelegate(window)->OnActivated();
+ }
+}
+
+void ActivationController::DeactivateWindow(aura::Window* window) {
+ if (window)
+ ActivateNextWindow(window);
+}
+
+aura::Window* ActivationController::GetActiveWindow() {
+ return reinterpret_cast<aura::Window*>(
+ aura::RootWindow::GetInstance()->GetProperty(
+ aura::kRootWindowActiveWindow));
+}
+
+bool ActivationController::CanFocusWindow(aura::Window* window) const {
+ return CanActivateWindow(GetActivatableWindow(window));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// ActivationController, aura::WindowObserver implementation:
+
+void ActivationController::OnWindowVisibilityChanged(aura::Window* window,
+ bool visible) {
+ if (!visible)
+ ActivateNextWindow(window);
+}
+
+void ActivationController::OnWindowDestroyed(aura::Window* window) {
+ if (IsActiveWindow(window)) {
+ // Clear the property before activating something else, since
+ // ActivateWindow() will attempt to notify the window stored in this value
+ // otherwise.
+ aura::RootWindow::GetInstance()->SetProperty(aura::kRootWindowActiveWindow,
+ NULL);
+ ActivateWindow(GetTopmostWindowToActivate(window));
+ }
+ window->RemoveObserver(this);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// ActivationController, aura::RootWindowObserver implementation:
+
+void ActivationController::OnWindowInitialized(aura::Window* window) {
+ window->AddObserver(this);
+}
+
+void ActivationController::OnWindowFocused(aura::Window* window) {
+ ActivateWindow(GetActivatableWindow(window));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// ActivationController, private:
+
+void ActivationController::ActivateNextWindow(aura::Window* window) {
+ if (IsActiveWindow(window))
+ ActivateWindow(GetTopmostWindowToActivate(window));
+}
+
+aura::Window* ActivationController::GetTopmostWindowToActivate(
+ aura::Window* ignore) const {
+ const aura::Window* container =
+ default_container_for_test_ ? default_container_for_test_ :
+ GetContainer(kShellWindowId_DefaultContainer);
+ for (aura::Window::Windows::const_reverse_iterator i =
+ container->children().rbegin();
+ i != container->children().rend();
+ ++i) {
+ if (*i != ignore && CanActivateWindow(*i))
+ return *i;
+ }
+ return NULL;
+}
+
+} // namespace internal
+} // namespace aura_shell
diff --git a/ui/aura_shell/activation_controller.h b/ui/aura_shell/activation_controller.h
new file mode 100644
index 0000000..226c26c
--- /dev/null
+++ b/ui/aura_shell/activation_controller.h
@@ -0,0 +1,74 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_AURA_SHELL_ACTIVATION_CONTROLLER_H_
+#define UI_AURA_SHELL_ACTIVATION_CONTROLLER_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "ui/aura/client/activation_client.h"
+#include "ui/aura/root_window_observer.h"
+#include "ui/aura/window_observer.h"
+
+namespace aura_shell {
+namespace internal {
+
+class ActivationController : public aura::ActivationClient,
+ public aura::WindowObserver,
+ public aura::RootWindowObserver {
+ public:
+ ActivationController();
+ virtual ~ActivationController();
+
+ // Returns true if |window| exists within a container that supports
+ // activation.
+ static aura::Window* GetActivatableWindow(aura::Window* window);
+
+ // Overridden from aura::ActivationClient:
+ virtual void ActivateWindow(aura::Window* window) OVERRIDE;
+ virtual void DeactivateWindow(aura::Window* window) OVERRIDE;
+ virtual aura::Window* GetActiveWindow() OVERRIDE;
+ virtual bool CanFocusWindow(aura::Window* window) const OVERRIDE;
+
+ // Overridden from aura::WindowObserver:
+ virtual void OnWindowVisibilityChanged(aura::Window* window,
+ bool visible) OVERRIDE;
+ virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE;
+
+ // Overridden from aura::RootWindowObserver:
+ virtual void OnWindowInitialized(aura::Window* window) OVERRIDE;
+ virtual void OnWindowFocused(aura::Window* window) OVERRIDE;
+
+#if defined(UNIT_TEST)
+ void set_default_container_for_test(aura::Window* window) {
+ default_container_for_test_ = window;
+ }
+#endif
+
+ private:
+ // Shifts activation to the next window, ignoring |window|.
+ void ActivateNextWindow(aura::Window* window);
+
+ // Returns the next window that should be activated, ignoring |ignore|.
+ aura::Window* GetTopmostWindowToActivate(aura::Window* ignore) const;
+
+ // True inside ActivateWindow(). Used to prevent recursion of focus
+ // change notifications causing activation.
+ bool updating_activation_;
+
+ // For tests that are not running with a Shell instance,
+ // ActivationController's attempts to locate the next active window in
+ // GetTopmostWindowToActivate() will crash, so we provide this way for such
+ // tests to specify a default container.
+ aura::Window* default_container_for_test_;
+
+ DISALLOW_COPY_AND_ASSIGN(ActivationController);
+};
+
+} // namespace internal
+} // namespace aura_shell
+
+#endif // UI_AURA_SHELL_ACTIVATION_CONTROLLER_H_
diff --git a/ui/aura_shell/activation_controller_unittest.cc b/ui/aura_shell/activation_controller_unittest.cc
new file mode 100644
index 0000000..b5529cd
--- /dev/null
+++ b/ui/aura_shell/activation_controller_unittest.cc
@@ -0,0 +1,281 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/aura_shell/activation_controller.h"
+
+#include "ui/aura/client/aura_constants.h"
+#include "ui/aura/focus_manager.h"
+#include "ui/aura/root_window.h"
+#include "ui/aura/test/event_generator.h"
+#include "ui/aura/test/test_windows.h"
+#include "ui/aura/test/test_window_delegate.h"
+#include "ui/aura_shell/test/aura_shell_test_base.h"
+#include "ui/aura_shell/test/test_activation_delegate.h"
+#include "ui/aura_shell/window_util.h"
+
+#if defined(OS_WIN)
+// Windows headers define macros for these function names which screw with us.
+#if defined(CreateWindow)
+#undef CreateWindow
+#endif
+#endif
+
+namespace aura_shell {
+namespace test {
+
+typedef test::AuraShellTestBase ActivationControllerTest;
+
+// Utilities for a set of tests that test
+// ActivationController::GetTopmostWindowToActivate().
+class GetTopmostWindowToActivateTest : public ActivationControllerTest {
+ public:
+ GetTopmostWindowToActivateTest() : ad_1_(false), ad_3_(false) {}
+ virtual ~GetTopmostWindowToActivateTest() {}
+
+ // Overridden from ActivationControllerTest:
+ virtual void SetUp() OVERRIDE {
+ ActivationControllerTest::SetUp();
+ CreateWindows();
+ }
+ virtual void TearDown() OVERRIDE {
+ DestroyWindows();
+ ActivationControllerTest::TearDown();
+ }
+
+ protected:
+ aura::Window* w1() { return w1_.get(); }
+ aura::Window* w2() { return w2_.get(); }
+ aura::Window* w3() { return w3_.get(); }
+ aura::Window* w4() { return w4_.get(); }
+
+ void DestroyWindow2() {
+ w2_.reset();
+ }
+
+ private:
+ void CreateWindows() {
+ // Create four windows, the first and third are not activatable, the second
+ // and fourth are.
+ w1_.reset(CreateWindow(1, &ad_1_));
+ w2_.reset(CreateWindow(2, &ad_2_));
+ w3_.reset(CreateWindow(3, &ad_3_));
+ w4_.reset(CreateWindow(4, &ad_4_));
+ }
+
+ aura::Window* CreateWindow(int id, TestActivationDelegate* delegate) {
+ aura::Window* window = aura::test::CreateTestWindowWithDelegate(
+ &delegate_, id, gfx::Rect(), NULL);
+ delegate->SetWindow(window);
+ return window;
+ }
+
+ void DestroyWindows() {
+ w1_.reset();
+ w2_.reset();
+ w3_.reset();
+ w4_.reset();
+ }
+
+ aura::test::TestWindowDelegate delegate_;
+ TestActivationDelegate ad_1_;
+ TestActivationDelegate ad_2_;
+ TestActivationDelegate ad_3_;
+ TestActivationDelegate ad_4_;
+ scoped_ptr<aura::Window> w1_; // Non-activatable.
+ scoped_ptr<aura::Window> w2_; // Activatable.
+ scoped_ptr<aura::Window> w3_; // Non-activatable.
+ scoped_ptr<aura::Window> w4_; // Activatable.
+
+ DISALLOW_COPY_AND_ASSIGN(GetTopmostWindowToActivateTest);
+};
+
+// Hiding the active window should activate the next valid activatable window.
+TEST_F(GetTopmostWindowToActivateTest, HideActivatesNext) {
+ ActivateWindow(w2());
+ EXPECT_TRUE(IsActiveWindow(w2()));
+
+ w2()->Hide();
+ EXPECT_TRUE(IsActiveWindow(w4()));
+}
+
+// Destroying the active window should activate the next valid activatable
+// window.
+TEST_F(GetTopmostWindowToActivateTest, DestroyActivatesNext) {
+ ActivateWindow(w2());
+ EXPECT_TRUE(IsActiveWindow(w2()));
+
+ DestroyWindow2();
+ EXPECT_EQ(NULL, w2());
+ EXPECT_TRUE(IsActiveWindow(w4()));
+}
+
+// Deactivating the active window should activate the next valid activatable
+// window.
+TEST_F(GetTopmostWindowToActivateTest, DeactivateActivatesNext) {
+ ActivateWindow(w2());
+ EXPECT_TRUE(IsActiveWindow(w2()));
+
+ DeactivateWindow(w2());
+ EXPECT_TRUE(IsActiveWindow(w4()));
+}
+
+// Test if the clicking on a menu picks the transient parent as activatable
+// window.
+TEST_F(ActivationControllerTest, ClickOnMenu) {
+ aura::test::TestWindowDelegate wd;
+ TestActivationDelegate ad1;
+ TestActivationDelegate ad2(false);
+
+ scoped_ptr<aura::Window> w1(aura::test::CreateTestWindowWithDelegate(
+ &wd, 1, gfx::Rect(100, 100), NULL));
+ ad1.SetWindow(w1.get());
+ EXPECT_TRUE(IsActiveWindow(NULL));
+
+ // Clicking on an activatable window activtes the window.
+ aura::test::EventGenerator generator(w1.get());
+ generator.ClickLeftButton();
+ EXPECT_TRUE(IsActiveWindow(w1.get()));
+
+ // Creates a menu that covers the transient parent.
+ scoped_ptr<aura::Window> menu(aura::test::CreateTestWindowWithDelegateAndType(
+ &wd, aura::WINDOW_TYPE_MENU, 2, gfx::Rect(100, 100), NULL));
+ ad2.SetWindow(menu.get());
+ w1->AddTransientChild(menu.get());
+
+ // Clicking on a menu whose transient parent is active window shouldn't
+ // change the active window.
+ generator.ClickLeftButton();
+ EXPECT_TRUE(IsActiveWindow(w1.get()));
+}
+
+// Various assertions for activating/deactivating.
+TEST_F(ActivationControllerTest, Deactivate) {
+ aura::test::TestWindowDelegate d1;
+ aura::test::TestWindowDelegate d2;
+ scoped_ptr<aura::Window> w1(aura::test::CreateTestWindowWithDelegate(
+ &d1, 1, gfx::Rect(), NULL));
+ scoped_ptr<aura::Window> w2(aura::test::CreateTestWindowWithDelegate(
+ &d2, 2, gfx::Rect(), NULL));
+ aura::Window* parent = w1->parent();
+ parent->Show();
+ ASSERT_TRUE(parent);
+ ASSERT_EQ(2u, parent->children().size());
+ // Activate w2 and make sure it's active and frontmost.
+ ActivateWindow(w2.get());
+ EXPECT_TRUE(IsActiveWindow(w2.get()));
+ EXPECT_FALSE(IsActiveWindow(w1.get()));
+ EXPECT_EQ(w2.get(), parent->children()[1]);
+
+ // Activate w1 and make sure it's active and frontmost.
+ ActivateWindow(w1.get());
+ EXPECT_TRUE(IsActiveWindow(w1.get()));
+ EXPECT_FALSE(IsActiveWindow(w2.get()));
+ EXPECT_EQ(w1.get(), parent->children()[1]);
+
+ // Deactivate w1 and make sure w2 becomes active and frontmost.
+ DeactivateWindow(w1.get());
+ EXPECT_FALSE(IsActiveWindow(w1.get()));
+ EXPECT_TRUE(IsActiveWindow(w2.get()));
+ EXPECT_EQ(w2.get(), parent->children()[1]);
+}
+
+// Verifies that when WindowDelegate::OnLostActive is invoked the window is not
+// active.
+TEST_F(ActivationControllerTest, NotActiveInLostActive) {
+ TestActivationDelegate ad1;
+ aura::test::TestWindowDelegate wd;
+ scoped_ptr<aura::Window> w1(aura::test::CreateTestWindowWithDelegate(
+ &wd, 1, gfx::Rect(10, 10, 50, 50), NULL));
+ ad1.SetWindow(w1.get());
+ scoped_ptr<aura::Window> w2(aura::test::CreateTestWindowWithDelegate(
+ NULL, 1, gfx::Rect(10, 10, 50, 50), NULL));
+
+ // Activate w1.
+ ActivateWindow(w1.get());
+ EXPECT_TRUE(IsActiveWindow(w1.get()));
+
+ // Should not have gotten a OnLostActive yet.
+ EXPECT_EQ(0, ad1.lost_active_count());
+
+ // ActivateWindow(NULL) should not change the active window.
+ ActivateWindow(NULL);
+ EXPECT_TRUE(IsActiveWindow(w1.get()));
+
+ // Now activate another window.
+ ActivateWindow(w2.get());
+
+ // Should have gotten OnLostActive and w1 should not have been active at that
+ // time.
+ EXPECT_EQ(1, ad1.lost_active_count());
+ EXPECT_FALSE(ad1.window_was_active());
+}
+
+// Verifies that focusing another window or its children causes it to become
+// active.
+TEST_F(ActivationControllerTest, FocusTriggersActivation) {
+ aura::test::TestWindowDelegate wd;
+ scoped_ptr<aura::Window> w1(aura::test::CreateTestWindowWithDelegate(
+ &wd, -1, gfx::Rect(50, 50), NULL));
+ scoped_ptr<aura::Window> w2(aura::test::CreateTestWindowWithDelegate(
+ &wd, -2, gfx::Rect(50, 50), NULL));
+ scoped_ptr<aura::Window> w21(aura::test::CreateTestWindowWithDelegate(
+ &wd, -21, gfx::Rect(50, 50), w2.get()));
+
+ ActivateWindow(w1.get());
+ EXPECT_TRUE(IsActiveWindow(w1.get()));
+ EXPECT_TRUE(w1->HasFocus());
+
+ w2->Focus();
+ EXPECT_TRUE(IsActiveWindow(w2.get()));
+ EXPECT_TRUE(w2->HasFocus());
+
+ ActivateWindow(w1.get());
+ EXPECT_TRUE(IsActiveWindow(w1.get()));
+ EXPECT_TRUE(w1->HasFocus());
+
+ w21->Focus();
+ EXPECT_TRUE(IsActiveWindow(w2.get()));
+ EXPECT_TRUE(w21->HasFocus());
+}
+
+// Verifies that we prevent all attempts to focus a child of a non-activatable
+// window from claiming focus to that window.
+TEST_F(ActivationControllerTest, PreventFocusToNonActivatableWindow) {
+ aura::test::TestWindowDelegate wd;
+ scoped_ptr<aura::Window> w1(aura::test::CreateTestWindowWithDelegate(
+ &wd, -1, gfx::Rect(50, 50), NULL));
+ // The RootWindow itself is a non-activatable parent.
+ scoped_ptr<aura::Window> w2(aura::test::CreateTestWindowWithDelegate(
+ &wd, -2, gfx::Rect(50, 50), aura::RootWindow::GetInstance()));
+ scoped_ptr<aura::Window> w21(aura::test::CreateTestWindowWithDelegate(
+ &wd, -21, gfx::Rect(50, 50), w2.get()));
+
+ ActivateWindow(w1.get());
+ EXPECT_TRUE(IsActiveWindow(w1.get()));
+ EXPECT_TRUE(w1->HasFocus());
+
+ // Try activating |w2|. It's not a child of an activatable container, so it
+ // should neither be activated nor get focus.
+ ActivateWindow(w2.get());
+ EXPECT_FALSE(IsActiveWindow(w2.get()));
+ EXPECT_FALSE(w2->HasFocus());
+ EXPECT_TRUE(IsActiveWindow(w1.get()));
+ EXPECT_TRUE(w1->HasFocus());
+
+ // Try focusing |w2|. Same rules apply.
+ w2->Focus();
+ EXPECT_FALSE(IsActiveWindow(w2.get()));
+ EXPECT_FALSE(w2->HasFocus());
+ EXPECT_TRUE(IsActiveWindow(w1.get()));
+ EXPECT_TRUE(w1->HasFocus());
+
+ // Try focusing |w21|. Same rules apply.
+ EXPECT_FALSE(IsActiveWindow(w2.get()));
+ EXPECT_FALSE(w21->HasFocus());
+ EXPECT_TRUE(IsActiveWindow(w1.get()));
+ EXPECT_TRUE(w1->HasFocus());
+}
+
+} // namespace test
+} // namespace aura_shell
diff --git a/ui/aura_shell/aura_shell.gyp b/ui/aura_shell/aura_shell.gyp
index fc4f0d1..23bd5b1 100644
--- a/ui/aura_shell/aura_shell.gyp
+++ b/ui/aura_shell/aura_shell.gyp
@@ -33,6 +33,8 @@
],
'sources': [
# All .cc, .h under views, except unittests
+ 'activation_controller.cc',
+ 'activation_controller.h',
'always_on_top_controller.cc',
'always_on_top_controller.h',
'app_list.cc',
@@ -143,6 +145,7 @@
'aura_shell',
],
'sources': [
+ 'activation_controller_unittest.cc',
'default_container_layout_manager_unittest.cc',
'root_window_event_filter_unittest.cc',
'drag_drop_controller_unittest.cc',
@@ -155,11 +158,12 @@
'shadow_controller_unittest.cc',
'shell_accelerator_controller_unittest.cc',
'shell_unittest.cc',
- 'stacking_controller_unittest.cc',
'test_suite.cc',
'test_suite.h',
'test/aura_shell_test_base.cc',
'test/aura_shell_test_base.h',
+ 'test/test_activation_delegate.cc',
+ 'test/test_activation_delegate.h',
'toplevel_layout_manager_unittest.cc',
'toplevel_window_event_filter_unittest.cc',
'workspace_controller_unittest.cc',
diff --git a/ui/aura_shell/default_container_event_filter.cc b/ui/aura_shell/default_container_event_filter.cc
index 725beb8..2f9481c 100644
--- a/ui/aura_shell/default_container_event_filter.cc
+++ b/ui/aura_shell/default_container_event_filter.cc
@@ -7,8 +7,8 @@
#include "ui/aura/event.h"
#include "ui/aura/window.h"
#include "ui/aura_shell/default_container_layout_manager.h"
-#include "ui/aura_shell/stacking_controller.h"
#include "ui/aura_shell/window_frame.h"
+#include "ui/aura_shell/window_util.h"
#include "ui/base/hit_test.h"
namespace {
@@ -77,7 +77,7 @@ bool DefaultContainerEventFilter::PreHandleMouseEvent(aura::Window* target,
}
break;
case ui::ET_MOUSE_ENTERED:
- UpdateHoveredWindow(StackingController::GetActivatableWindow(target));
+ UpdateHoveredWindow(GetActivatableWindow(target));
break;
case ui::ET_MOUSE_EXITED:
UpdateHoveredWindow(NULL);
diff --git a/ui/aura_shell/default_container_layout_manager.cc b/ui/aura_shell/default_container_layout_manager.cc
index a9a93be..f3a77e9 100644
--- a/ui/aura_shell/default_container_layout_manager.cc
+++ b/ui/aura_shell/default_container_layout_manager.cc
@@ -13,6 +13,7 @@
#include "ui/aura/window_types.h"
#include "ui/aura_shell/property_util.h"
#include "ui/aura_shell/show_state_controller.h"
+#include "ui/aura_shell/window_util.h"
#include "ui/aura_shell/workspace/workspace.h"
#include "ui/aura_shell/workspace/workspace_manager.h"
#include "ui/base/ui_base_types.h"
@@ -105,7 +106,7 @@ void DefaultContainerLayoutManager::OnWindowAddedToLayout(aura::Window* child) {
Workspace* workspace = workspace_manager_->GetActiveWorkspace();
if (workspace) {
- aura::Window* active = aura::RootWindow::GetInstance()->active_window();
+ aura::Window* active = aura_shell::GetActiveWindow();
// Active window may not be in the default container layer.
if (!workspace->Contains(active))
active = NULL;
diff --git a/ui/aura_shell/examples/aura_shell_main.cc b/ui/aura_shell/examples/aura_shell_main.cc
index d0429c9..0700047 100644
--- a/ui/aura_shell/examples/aura_shell_main.cc
+++ b/ui/aura_shell/examples/aura_shell_main.cc
@@ -13,6 +13,7 @@
#include "ui/aura_shell/shell.h"
#include "ui/aura_shell/shell_delegate.h"
#include "ui/aura_shell/shell_factory.h"
+#include "ui/aura_shell/window_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/base/ui_base_paths.h"
#include "ui/gfx/canvas.h"
@@ -74,7 +75,7 @@ class ShellDelegateImpl : public aura_shell::ShellDelegate {
virtual void LauncherItemClicked(
const aura_shell::LauncherItem& item) OVERRIDE {
- item.window->Activate();
+ aura_shell::ActivateWindow(item.window);
}
virtual bool ConfigureLauncherItem(aura_shell::LauncherItem* item) OVERRIDE {
diff --git a/ui/aura_shell/modal_container_layout_manager.cc b/ui/aura_shell/modal_container_layout_manager.cc
index 9a29337..ccf5f7d 100644
--- a/ui/aura_shell/modal_container_layout_manager.cc
+++ b/ui/aura_shell/modal_container_layout_manager.cc
@@ -11,7 +11,7 @@
#include "ui/aura/window.h"
#include "ui/aura_shell/modality_event_filter.h"
#include "ui/aura_shell/shell.h"
-#include "ui/aura_shell/stacking_controller.h"
+#include "ui/aura_shell/window_util.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/compositor/layer.h"
#include "ui/gfx/compositor/layer_animator.h"
@@ -126,7 +126,7 @@ void ModalContainerLayoutManager::OnLayerAnimationScheduled(
bool ModalContainerLayoutManager::CanWindowReceiveEvents(
aura::Window* window) {
- return StackingController::GetActivatableWindow(window) == modal_window();
+ return GetActivatableWindow(window) == modal_window();
}
////////////////////////////////////////////////////////////////////////////////
@@ -135,8 +135,6 @@ bool ModalContainerLayoutManager::CanWindowReceiveEvents(
void ModalContainerLayoutManager::AddModalWindow(aura::Window* window) {
modal_windows_.push_back(window);
CreateModalScreen();
- container_->StackChildAtTop(window);
- window->Activate();
}
void ModalContainerLayoutManager::RemoveModalWindow(aura::Window* window) {
@@ -148,7 +146,7 @@ void ModalContainerLayoutManager::RemoveModalWindow(aura::Window* window) {
if (modal_windows_.empty())
HideModalScreen();
else
- modal_window()->Activate();
+ aura_shell::ActivateWindow(modal_window());
}
void ModalContainerLayoutManager::CreateModalScreen() {
diff --git a/ui/aura_shell/modal_container_layout_manager_unittest.cc b/ui/aura_shell/modal_container_layout_manager_unittest.cc
index 6adcce0..228b853 100644
--- a/ui/aura_shell/modal_container_layout_manager_unittest.cc
+++ b/ui/aura_shell/modal_container_layout_manager_unittest.cc
@@ -11,6 +11,7 @@
#include "ui/aura_shell/shell.h"
#include "ui/aura_shell/shell_window_ids.h"
#include "ui/aura_shell/test/aura_shell_test_base.h"
+#include "ui/aura_shell/window_util.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
@@ -81,7 +82,7 @@ class TransientWindowObserver : public aura::WindowObserver {
} // namespace
-typedef aura_shell::test::AuraShellTestBase ModalContainerLayoutManagerTest;
+typedef AuraShellTestBase ModalContainerLayoutManagerTest;
TEST_F(ModalContainerLayoutManagerTest, NonModalTransient) {
scoped_ptr<aura::Window> parent(TestWindow::OpenTestWindow(NULL, false));
@@ -100,7 +101,7 @@ TEST_F(ModalContainerLayoutManagerTest, NonModalTransient) {
TEST_F(ModalContainerLayoutManagerTest, ModalTransient) {
scoped_ptr<aura::Window> parent(TestWindow::OpenTestWindow(NULL, false));
// parent should be active.
- EXPECT_EQ(parent.get(), aura::RootWindow::GetInstance()->active_window());
+ EXPECT_TRUE(IsActiveWindow(parent.get()));
aura::Window* t1 = TestWindow::OpenTestWindow(parent.get(), true);
TransientWindowObserver do1;
@@ -110,19 +111,19 @@ TEST_F(ModalContainerLayoutManagerTest, ModalTransient) {
EXPECT_EQ(GetModalContainer(), t1->parent());
// t1 should now be active.
- EXPECT_EQ(t1, aura::RootWindow::GetInstance()->active_window());
+ EXPECT_TRUE(IsActiveWindow(t1));
// Attempting to click the parent should result in no activation change.
aura::test::EventGenerator e1(parent.get());
e1.ClickLeftButton();
- EXPECT_EQ(t1, aura::RootWindow::GetInstance()->active_window());
+ EXPECT_TRUE(IsActiveWindow(t1));
// Now open another modal transient parented to the original modal transient.
aura::Window* t2 = TestWindow::OpenTestWindow(t1, true);
TransientWindowObserver do2;
t2->AddObserver(&do2);
- EXPECT_EQ(t2, aura::RootWindow::GetInstance()->active_window());
+ EXPECT_TRUE(IsActiveWindow(t2));
EXPECT_EQ(t1, t2->transient_parent());
EXPECT_EQ(GetModalContainer(), t2->parent());
@@ -130,7 +131,7 @@ TEST_F(ModalContainerLayoutManagerTest, ModalTransient) {
// t2 should still be active, even after clicking on t1.
aura::test::EventGenerator e2(t1);
e2.ClickLeftButton();
- EXPECT_EQ(t2, aura::RootWindow::GetInstance()->active_window());
+ EXPECT_TRUE(IsActiveWindow(t2));
// Both transients should be destroyed with parent.
parent.reset();
@@ -145,28 +146,28 @@ TEST_F(ModalContainerLayoutManagerTest, CanActivateAfterEndModalSession) {
unrelated->SetBounds(gfx::Rect(100, 100, 50, 50));
scoped_ptr<aura::Window> parent(TestWindow::OpenTestWindow(NULL, false));
// parent should be active.
- EXPECT_EQ(parent.get(), aura::RootWindow::GetInstance()->active_window());
+ EXPECT_TRUE(IsActiveWindow(parent.get()));
scoped_ptr<aura::Window> transient(
TestWindow::OpenTestWindow(parent.get(), true));
// t1 should now be active.
- EXPECT_EQ(transient.get(), aura::RootWindow::GetInstance()->active_window());
+ EXPECT_TRUE(IsActiveWindow(transient.get()));
// Attempting to click the parent should result in no activation change.
aura::test::EventGenerator e1(parent.get());
e1.ClickLeftButton();
- EXPECT_EQ(transient.get(), aura::RootWindow::GetInstance()->active_window());
+ EXPECT_TRUE(IsActiveWindow(transient.get()));
// Now close the transient.
transient.reset();
// parent should now be active again.
- EXPECT_EQ(parent.get(), aura::RootWindow::GetInstance()->active_window());
+ EXPECT_TRUE(IsActiveWindow(parent.get()));
// Attempting to click unrelated should activate it.
aura::test::EventGenerator e2(unrelated.get());
e2.ClickLeftButton();
- EXPECT_EQ(unrelated.get(), aura::RootWindow::GetInstance()->active_window());
+ EXPECT_TRUE(IsActiveWindow(unrelated.get()));
}
} // namespace test
diff --git a/ui/aura_shell/root_window_event_filter.cc b/ui/aura_shell/root_window_event_filter.cc
index 9d1f3db..b627341 100644
--- a/ui/aura_shell/root_window_event_filter.cc
+++ b/ui/aura_shell/root_window_event_filter.cc
@@ -8,8 +8,9 @@
#include "ui/aura/focus_manager.h"
#include "ui/aura/root_window.h"
#include "ui/aura/window_delegate.h"
+#include "ui/aura_shell/activation_controller.h"
#include "ui/aura_shell/shell.h"
-#include "ui/aura_shell/stacking_controller.h"
+#include "ui/aura_shell/window_util.h"
#include "ui/base/hit_test.h"
namespace aura_shell {
@@ -79,7 +80,7 @@ bool RootWindowEventFilter::PreHandleMouseEvent(aura::Window* target,
return true;
if (event->type() == ui::ET_MOUSE_PRESSED)
- ActivateIfNecessary(target, event);
+ target->GetFocusManager()->SetFocusedWindow(target);
return false;
}
@@ -92,24 +93,13 @@ ui::TouchStatus RootWindowEventFilter::PreHandleTouchEvent(
return status;
if (event->type() == ui::ET_TOUCH_PRESSED)
- ActivateIfNecessary(target, event);
+ target->GetFocusManager()->SetFocusedWindow(target);
return ui::TOUCH_STATUS_UNKNOWN;
}
////////////////////////////////////////////////////////////////////////////////
// RootWindowEventFilter, private:
-void RootWindowEventFilter::ActivateIfNecessary(aura::Window* window,
- aura::Event* event) {
- aura::Window* activatable = StackingController::GetActivatableWindow(window);
- if (activatable == aura::RootWindow::GetInstance()->active_window()) {
- // |window| is a descendant of the active window, no need to activate.
- window->GetFocusManager()->SetFocusedWindow(window);
- } else {
- aura::RootWindow::GetInstance()->SetActiveWindow(activatable, window);
- }
-}
-
void RootWindowEventFilter::UpdateCursor(aura::Window* target,
aura::MouseEvent* event) {
gfx::NativeCursor cursor = target->GetCursor(event->location());
diff --git a/ui/aura_shell/root_window_event_filter.h b/ui/aura_shell/root_window_event_filter.h
index 20afc03..8392aa4 100644
--- a/ui/aura_shell/root_window_event_filter.h
+++ b/ui/aura_shell/root_window_event_filter.h
@@ -40,14 +40,11 @@ class AURA_SHELL_EXPORT RootWindowEventFilter : public aura::EventFilter {
aura::TouchEvent* event) OVERRIDE;
private:
- // If necessary, activates |window| and changes focus.
- void ActivateIfNecessary(aura::Window* window, aura::Event* event);
-
// Updates the cursor if the target provides a custom one, and provides
// default resize cursors for window edges.
void UpdateCursor(aura::Window* target, aura::MouseEvent* event);
- // Dispatches event to addtional filters. Returns false or
+ // Dispatches event to additional filters. Returns false or
// ui::TOUCH_STATUS_UNKNOWN if event is consumed.
bool FilterKeyEvent(aura::Window* target, aura::KeyEvent* event);
bool FilterMouseEvent(aura::Window* target, aura::MouseEvent* event);
diff --git a/ui/aura_shell/root_window_event_filter_unittest.cc b/ui/aura_shell/root_window_event_filter_unittest.cc
index 0f4302b..d53cdc8 100644
--- a/ui/aura_shell/root_window_event_filter_unittest.cc
+++ b/ui/aura_shell/root_window_event_filter_unittest.cc
@@ -4,6 +4,8 @@
#include "ui/aura_shell/root_window_event_filter.h"
+#include "ui/aura/client/activation_delegate.h"
+#include "ui/aura/client/aura_constants.h"
#include "ui/aura/cursor.h"
#include "ui/aura/event.h"
#include "ui/aura/root_window.h"
@@ -13,7 +15,10 @@
#include "ui/aura/test/test_event_filter.h"
#include "ui/aura/test/test_window_delegate.h"
#include "ui/aura/test/test_stacking_client.h"
+#include "ui/aura_shell/activation_controller.h"
#include "ui/aura_shell/shell_window_ids.h"
+#include "ui/aura_shell/test/test_activation_delegate.h"
+#include "ui/aura_shell/window_util.h"
#include "ui/base/hit_test.h"
#include "ui/gfx/screen.h"
@@ -31,12 +36,17 @@ class RootWindowEventFilterTest : public aura::test::AuraTestBase {
aura::RootWindow::GetInstance()->stacking_client());
stacking_client->default_container()->set_id(
internal::kShellWindowId_DefaultContainer);
+ activation_controller_.reset(new internal::ActivationController);
+ activation_controller_->set_default_container_for_test(
+ stacking_client->default_container());
}
virtual ~RootWindowEventFilterTest() {
aura::RootWindow::GetInstance()->SetEventFilter(NULL);
}
private:
+ scoped_ptr<internal::ActivationController> activation_controller_;
+
DISALLOW_COPY_AND_ASSIGN(RootWindowEventFilterTest);
};
@@ -124,63 +134,72 @@ TEST_F(RootWindowEventFilterTest, Focus) {
TEST_F(RootWindowEventFilterTest, ActivateOnMouse) {
aura::RootWindow* root_window = aura::RootWindow::GetInstance();
- aura::test::ActivateWindowDelegate d1;
+ TestActivationDelegate d1;
+ aura::test::TestWindowDelegate wd;
scoped_ptr<aura::Window> w1(aura::test::CreateTestWindowWithDelegate(
- &d1, 1, gfx::Rect(10, 10, 50, 50), NULL));
- aura::test::ActivateWindowDelegate d2;
+ &wd, 1, gfx::Rect(10, 10, 50, 50), NULL));
+ d1.SetWindow(w1.get());
+ TestActivationDelegate d2;
scoped_ptr<aura::Window> w2(aura::test::CreateTestWindowWithDelegate(
- &d2, 2, gfx::Rect(70, 70, 50, 50), NULL));
+ &wd, 2, gfx::Rect(70, 70, 50, 50), NULL));
+ d2.SetWindow(w2.get());
+
aura::internal::FocusManager* focus_manager = w1->GetFocusManager();
d1.Clear();
d2.Clear();
// Activate window1.
- root_window->SetActiveWindow(w1.get(), NULL);
- EXPECT_EQ(w1.get(), root_window->active_window());
+ aura_shell::ActivateWindow(w1.get());
+ EXPECT_TRUE(IsActiveWindow(w1.get()));
EXPECT_EQ(w1.get(), focus_manager->GetFocusedWindow());
EXPECT_EQ(1, d1.activated_count());
EXPECT_EQ(0, d1.lost_active_count());
d1.Clear();
- // Click on window2.
- gfx::Point press_point = w2->bounds().CenterPoint();
- aura::Window::ConvertPointToWindow(w2->parent(), root_window, &press_point);
- aura::test::EventGenerator generator(press_point);
- generator.ClickLeftButton();
-
- // Window2 should have become active.
- EXPECT_EQ(w2.get(), root_window->active_window());
- EXPECT_EQ(w2.get(), focus_manager->GetFocusedWindow());
- EXPECT_EQ(0, d1.activated_count());
- EXPECT_EQ(1, d1.lost_active_count());
- EXPECT_EQ(1, d2.activated_count());
- EXPECT_EQ(0, d2.lost_active_count());
- d1.Clear();
- d2.Clear();
-
- // Click back on window1, but set it up so w1 doesn't activate on click.
- press_point = w1->bounds().CenterPoint();
- aura::Window::ConvertPointToWindow(w1->parent(), root_window, &press_point);
- d1.set_activate(false);
- generator.ClickLeftButton();
+ {
+ // Click on window2.
+ gfx::Point press_point = w2->bounds().CenterPoint();
+ aura::Window::ConvertPointToWindow(w2->parent(), root_window, &press_point);
+ aura::test::EventGenerator generator(press_point);
+ generator.ClickLeftButton();
+
+ // Window2 should have become active.
+ EXPECT_TRUE(IsActiveWindow(w2.get()));
+ EXPECT_EQ(w2.get(), focus_manager->GetFocusedWindow());
+ EXPECT_EQ(0, d1.activated_count());
+ EXPECT_EQ(1, d1.lost_active_count());
+ EXPECT_EQ(1, d2.activated_count());
+ EXPECT_EQ(0, d2.lost_active_count());
+ d1.Clear();
+ d2.Clear();
+ }
- // Window2 should still be active and focused.
- EXPECT_EQ(w2.get(), root_window->active_window());
- EXPECT_EQ(w2.get(), focus_manager->GetFocusedWindow());
- EXPECT_EQ(0, d1.activated_count());
- EXPECT_EQ(0, d1.lost_active_count());
- EXPECT_EQ(0, d2.activated_count());
- EXPECT_EQ(0, d2.lost_active_count());
- d1.Clear();
- d2.Clear();
+ {
+ // Click back on window1, but set it up so w1 doesn't activate on click.
+ gfx::Point press_point = w1->bounds().CenterPoint();
+ aura::Window::ConvertPointToWindow(w1->parent(), root_window, &press_point);
+ aura::test::EventGenerator generator(press_point);
+ d1.set_activate(false);
+ generator.ClickLeftButton();
+
+ // Window2 should still be active and focused.
+ EXPECT_TRUE(IsActiveWindow(w2.get()));
+ EXPECT_EQ(w2.get(), focus_manager->GetFocusedWindow());
+ EXPECT_EQ(0, d1.activated_count());
+ EXPECT_EQ(0, d1.lost_active_count());
+ EXPECT_EQ(0, d2.activated_count());
+ EXPECT_EQ(0, d2.lost_active_count());
+ d1.Clear();
+ d2.Clear();
+ }
// Destroy window2, this should make window1 active.
d1.set_activate(true);
w2.reset();
EXPECT_EQ(0, d2.activated_count());
EXPECT_EQ(0, d2.lost_active_count());
- EXPECT_EQ(w1.get(), root_window->active_window());
+ EXPECT_TRUE(IsActiveWindow(w1.get()));
EXPECT_EQ(w1.get(), focus_manager->GetFocusedWindow());
EXPECT_EQ(1, d1.activated_count());
EXPECT_EQ(0, d1.lost_active_count());
@@ -190,20 +209,24 @@ TEST_F(RootWindowEventFilterTest, ActivateOnMouse) {
TEST_F(RootWindowEventFilterTest, ActivateOnTouch) {
aura::RootWindow* root_window = aura::RootWindow::GetInstance();
- aura::test::ActivateWindowDelegate d1;
+ TestActivationDelegate d1;
+ aura::test::TestWindowDelegate wd;
scoped_ptr<aura::Window> w1(aura::test::CreateTestWindowWithDelegate(
- &d1, -1, gfx::Rect(10, 10, 50, 50), NULL));
- aura::test::ActivateWindowDelegate d2;
+ &wd, -1, gfx::Rect(10, 10, 50, 50), NULL));
+ d1.SetWindow(w1.get());
+ TestActivationDelegate d2;
scoped_ptr<aura::Window> w2(aura::test::CreateTestWindowWithDelegate(
- &d2, -2, gfx::Rect(70, 70, 50, 50), NULL));
+ &wd, -2, gfx::Rect(70, 70, 50, 50), NULL));
+ d2.SetWindow(w2.get());
+
aura::internal::FocusManager* focus_manager = w1->GetFocusManager();
d1.Clear();
d2.Clear();
// Activate window1.
- root_window->SetActiveWindow(w1.get(), NULL);
- EXPECT_EQ(w1.get(), root_window->active_window());
+ aura_shell::ActivateWindow(w1.get());
+ EXPECT_TRUE(IsActiveWindow(w1.get()));
EXPECT_EQ(w1.get(), focus_manager->GetFocusedWindow());
EXPECT_EQ(1, d1.activated_count());
EXPECT_EQ(0, d1.lost_active_count());
@@ -216,7 +239,7 @@ TEST_F(RootWindowEventFilterTest, ActivateOnTouch) {
root_window->DispatchTouchEvent(&touchev1);
// Window2 should have become active.
- EXPECT_EQ(w2.get(), root_window->active_window());
+ EXPECT_TRUE(IsActiveWindow(w2.get()));
EXPECT_EQ(w2.get(), focus_manager->GetFocusedWindow());
EXPECT_EQ(0, d1.activated_count());
EXPECT_EQ(1, d1.lost_active_count());
@@ -233,7 +256,7 @@ TEST_F(RootWindowEventFilterTest, ActivateOnTouch) {
root_window->DispatchTouchEvent(&touchev2);
// Window2 should still be active and focused.
- EXPECT_EQ(w2.get(), root_window->active_window());
+ EXPECT_TRUE(IsActiveWindow(w2.get()));
EXPECT_EQ(w2.get(), focus_manager->GetFocusedWindow());
EXPECT_EQ(0, d1.activated_count());
EXPECT_EQ(0, d1.lost_active_count());
@@ -247,7 +270,7 @@ TEST_F(RootWindowEventFilterTest, ActivateOnTouch) {
w2.reset();
EXPECT_EQ(0, d2.activated_count());
EXPECT_EQ(0, d2.lost_active_count());
- EXPECT_EQ(w1.get(), root_window->active_window());
+ EXPECT_TRUE(IsActiveWindow(w1.get()));
EXPECT_EQ(w1.get(), focus_manager->GetFocusedWindow());
EXPECT_EQ(1, d1.activated_count());
EXPECT_EQ(0, d1.lost_active_count());
@@ -329,9 +352,11 @@ TEST_F(RootWindowEventFilterTest, TransformActivate) {
transform.ConcatTranslate(size.width(), 0);
root_window->SetTransform(transform);
- aura::test::ActivateWindowDelegate d1;
+ TestActivationDelegate d1;
+ aura::test::TestWindowDelegate wd;
scoped_ptr<aura::Window> w1(
- CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(0, 10, 50, 50), NULL));
+ CreateTestWindowWithDelegate(&wd, 1, gfx::Rect(0, 10, 50, 50), NULL));
+ d1.SetWindow(w1.get());
w1->Show();
gfx::Point miss_point(5, 5);
@@ -352,7 +377,7 @@ TEST_F(RootWindowEventFilterTest, TransformActivate) {
hit_point,
ui::EF_LEFT_BUTTON_DOWN);
root_window->DispatchMouseEvent(&mouseev2);
- EXPECT_EQ(w1.get(), root_window->active_window());
+ EXPECT_TRUE(IsActiveWindow(w1.get()));
EXPECT_EQ(w1.get(), w1->GetFocusManager()->GetFocusedWindow());
}
@@ -362,7 +387,7 @@ TEST_F(RootWindowEventFilterTest, AdditionalFilters) {
// Creates a window and make it active
scoped_ptr<aura::Window> w1(aura::test::CreateTestWindow(
SK_ColorWHITE, -1, gfx::Rect(0, 0, 100, 100), NULL));
- root_window->SetActiveWindow(w1.get(), NULL);
+ aura_shell::ActivateWindow(w1.get());
// Creates two addition filters
scoped_ptr<aura::test::TestEventFilter> f1(
diff --git a/ui/aura_shell/shadow_controller.cc b/ui/aura_shell/shadow_controller.cc
index b93876e..46670ff 100644
--- a/ui/aura_shell/shadow_controller.cc
+++ b/ui/aura_shell/shadow_controller.cc
@@ -19,7 +19,7 @@ namespace aura_shell {
namespace internal {
ShadowController::ShadowController() {
- aura::RootWindow::GetInstance()->AddObserver(this);
+ aura::RootWindow::GetInstance()->AddRootWindowObserver(this);
}
ShadowController::~ShadowController() {
@@ -27,7 +27,7 @@ ShadowController::~ShadowController() {
it != window_shadows_.end(); ++it) {
it->first->RemoveObserver(this);
}
- aura::RootWindow::GetInstance()->RemoveObserver(this);
+ aura::RootWindow::GetInstance()->RemoveRootWindowObserver(this);
}
void ShadowController::OnWindowInitialized(aura::Window* window) {
diff --git a/ui/aura_shell/shell.cc b/ui/aura_shell/shell.cc
index cf55c7bb..87be5ac 100644
--- a/ui/aura_shell/shell.cc
+++ b/ui/aura_shell/shell.cc
@@ -13,6 +13,7 @@
#include "ui/aura/layout_manager.h"
#include "ui/aura/window.h"
#include "ui/aura/window_types.h"
+#include "ui/aura_shell/activation_controller.h"
#include "ui/aura_shell/app_list.h"
#include "ui/aura_shell/default_container_event_filter.h"
#include "ui/aura_shell/default_container_layout_manager.h"
@@ -178,6 +179,8 @@ void Shell::Init() {
aura::RootWindow* root_window = aura::RootWindow::GetInstance();
root_window->SetCursor(aura::kCursorPointer);
+ activation_controller_.reset(new internal::ActivationController);
+
aura::Window::Windows containers;
CreateSpecialContainers(&containers);
aura::Window::Windows::const_iterator i;
diff --git a/ui/aura_shell/shell.h b/ui/aura_shell/shell.h
index a877863..cbb904e 100644
--- a/ui/aura_shell/shell.h
+++ b/ui/aura_shell/shell.h
@@ -32,6 +32,7 @@ class ShellDelegate;
class ShellTooltipManager;
namespace internal {
+class ActivationController;
class AppList;
class DragDropController;
class ShadowController;
@@ -109,6 +110,7 @@ class AURA_SHELL_EXPORT Shell {
scoped_ptr<internal::AppList> app_list_;
+ scoped_ptr<internal::ActivationController> activation_controller_;
scoped_ptr<internal::DragDropController> drag_drop_controller_;
scoped_ptr<internal::WorkspaceController> workspace_controller_;
scoped_ptr<internal::ShadowController> shadow_controller_;
diff --git a/ui/aura_shell/stacking_controller.cc b/ui/aura_shell/stacking_controller.cc
index 08c7da8..dba6da1 100644
--- a/ui/aura_shell/stacking_controller.cc
+++ b/ui/aura_shell/stacking_controller.cc
@@ -19,14 +19,6 @@ aura::Window* GetContainer(int id) {
return Shell::GetInstance()->GetContainer(id);
}
-// Returns true if children of |window| can be activated.
-bool SupportsChildActivation(aura::Window* window) {
- return window->id() == kShellWindowId_DefaultContainer ||
- window->id() == kShellWindowId_AlwaysOnTopContainer ||
- window->id() == kShellWindowId_ModalContainer ||
- window->id() == kShellWindowId_LockModalContainer;
-}
-
bool IsWindowModal(aura::Window* window) {
return window->transient_parent() && window->GetIntProperty(aura::kModalKey);
}
@@ -50,23 +42,6 @@ void StackingController::Init() {
GetContainer(internal::kShellWindowId_AlwaysOnTopContainer));
}
-// static
-aura::Window* StackingController::GetActivatableWindow(aura::Window* window) {
- aura::Window* parent = window->parent();
- aura::Window* child = window;
- while (parent) {
- if (SupportsChildActivation(parent))
- return child;
- // If |child| isn't activatable, but has transient parent, trace
- // that path instead.
- if (child->transient_parent())
- return GetActivatableWindow(child->transient_parent());
- parent = parent->parent();
- child = child->parent();
- }
- return NULL;
-}
-
////////////////////////////////////////////////////////////////////////////////
// StackingController, aura::StackingClient implementation:
@@ -93,24 +68,6 @@ void StackingController::AddChildToDefaultParent(aura::Window* window) {
parent->AddChild(window);
}
-bool StackingController::CanActivateWindow(aura::Window* window) const {
- return window && SupportsChildActivation(window->parent());
-}
-
-aura::Window* StackingController::GetTopmostWindowToActivate(
- aura::Window* ignore) const {
- const aura::Window* container = GetContainer(kShellWindowId_DefaultContainer);
- for (aura::Window::Windows::const_reverse_iterator i =
- container->children().rbegin();
- i != container->children().rend();
- ++i) {
- if (*i != ignore && (*i)->CanActivate())
- return *i;
- }
- return NULL;
-}
-
-
////////////////////////////////////////////////////////////////////////////////
// StackingController, private:
diff --git a/ui/aura_shell/stacking_controller.h b/ui/aura_shell/stacking_controller.h
index 7be9966..d7b2edd 100644
--- a/ui/aura_shell/stacking_controller.h
+++ b/ui/aura_shell/stacking_controller.h
@@ -24,15 +24,8 @@ class StackingController : public aura::StackingClient {
// Initializes this controller.
void Init();
- // Returns true if |window| exists within a container that supports
- // activation.
- static aura::Window* GetActivatableWindow(aura::Window* window);
-
// Overridden from aura::StackingClient:
virtual void AddChildToDefaultParent(aura::Window* window) OVERRIDE;
- virtual bool CanActivateWindow(aura::Window* window) const OVERRIDE;
- virtual aura::Window* GetTopmostWindowToActivate(
- aura::Window* ignore) const OVERRIDE;
private:
// Returns corresponding modal container for a modal window.
diff --git a/ui/aura_shell/stacking_controller_unittest.cc b/ui/aura_shell/stacking_controller_unittest.cc
index 5b8fa09..e69de29 100644
--- a/ui/aura_shell/stacking_controller_unittest.cc
+++ b/ui/aura_shell/stacking_controller_unittest.cc
@@ -1,59 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/aura_shell/stacking_controller.h"
-
-#include "ui/aura/root_window.h"
-#include "ui/aura/test/event_generator.h"
-#include "ui/aura/test/test_windows.h"
-#include "ui/aura/test/test_window_delegate.h"
-#include "ui/aura_shell/test/aura_shell_test_base.h"
-
-namespace aura_shell {
-namespace test {
-
-typedef aura_shell::test::AuraShellTestBase StackingControllerTest;
-
-TEST_F(StackingControllerTest, GetTopmostWindowToActivate) {
- aura::test::ActivateWindowDelegate activate;
- aura::test::ActivateWindowDelegate non_activate(false);
-
- scoped_ptr<aura::Window> w1(aura::test::CreateTestWindowWithDelegate(
- &non_activate, 1, gfx::Rect(), NULL));
- scoped_ptr<aura::Window> w2(aura::test::CreateTestWindowWithDelegate(
- &activate, 2, gfx::Rect(), NULL));
- scoped_ptr<aura::Window> w3(aura::test::CreateTestWindowWithDelegate(
- &non_activate, 3, gfx::Rect(), NULL));
- EXPECT_EQ(w2.get(), aura::RootWindow::GetInstance()->stacking_client()->
- GetTopmostWindowToActivate(NULL));
-}
-
-// Test if the clicking on a menu picks the transient parent as activatable
-// window.
-TEST_F(StackingControllerTest, ClickOnMenu) {
- aura::test::ActivateWindowDelegate activate;
- aura::test::ActivateWindowDelegate non_activate(false);
-
- scoped_ptr<aura::Window> w1(aura::test::CreateTestWindowWithDelegate(
- &activate, 1, gfx::Rect(100, 100), NULL));
- EXPECT_EQ(NULL, aura::RootWindow::GetInstance()->active_window());
-
- // Clicking on an activatable window activtes the window.
- aura::test::EventGenerator generator(w1.get());
- generator.ClickLeftButton();
- EXPECT_EQ(w1.get(), aura::RootWindow::GetInstance()->active_window());
-
- // Creates a menu that covers the transient parent.
- scoped_ptr<aura::Window> menu(aura::test::CreateTestWindowWithDelegateAndType(
- &non_activate, aura::WINDOW_TYPE_MENU, 2, gfx::Rect(100, 100), NULL));
- w1->AddTransientChild(menu.get());
-
- // Clicking on a menu whose transient parent is active window shouldn't
- // change the active window.
- generator.ClickLeftButton();
- EXPECT_EQ(w1.get(), aura::RootWindow::GetInstance()->active_window());
-}
-
-} // namespace test
-} // namespace aura_shell
diff --git a/ui/aura_shell/test/test_activation_delegate.cc b/ui/aura_shell/test/test_activation_delegate.cc
new file mode 100644
index 0000000..ac63bdb
--- /dev/null
+++ b/ui/aura_shell/test/test_activation_delegate.cc
@@ -0,0 +1,53 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/aura_shell/test/test_activation_delegate.h"
+
+#include "ui/aura/client/aura_constants.h"
+#include "ui/aura/window.h"
+#include "ui/aura_shell/window_util.h"
+
+namespace aura_shell {
+namespace test {
+
+////////////////////////////////////////////////////////////////////////////////
+// TestActivationDelegate
+
+TestActivationDelegate::TestActivationDelegate()
+ : window_(NULL),
+ window_was_active_(false),
+ activate_(true),
+ activated_count_(0),
+ lost_active_count_(0),
+ should_activate_count_(0) {
+}
+
+TestActivationDelegate::TestActivationDelegate(bool activate)
+ : window_(NULL),
+ window_was_active_(false),
+ activate_(activate),
+ activated_count_(0),
+ lost_active_count_(0),
+ should_activate_count_(0) {
+}
+
+void TestActivationDelegate::SetWindow(aura::Window* window) {
+ window_ = window;
+ aura::ActivationDelegate::SetActivationDelegate(window, this);
+}
+
+bool TestActivationDelegate::ShouldActivate(aura::Event* event) {
+ should_activate_count_++;
+ return activate_;
+}
+void TestActivationDelegate::OnActivated() {
+ activated_count_++;
+}
+void TestActivationDelegate::OnLostActive() {
+ if (lost_active_count_++ == 0)
+ window_was_active_ = IsActiveWindow(window_);
+}
+
+} // namespace test
+} // namespace aura_shell
diff --git a/ui/aura_shell/test/test_activation_delegate.h b/ui/aura_shell/test/test_activation_delegate.h
new file mode 100644
index 0000000..d3f1c85
--- /dev/null
+++ b/ui/aura_shell/test/test_activation_delegate.h
@@ -0,0 +1,59 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_AURA_SHELL_TEST_TEST_ACTIVATION_DELEGATE_H_
+#define UI_AURA_SHELL_TEST_TEST_ACTIVATION_DELEGATE_H_
+#pragma once
+
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "ui/aura/client/activation_delegate.h"
+
+namespace aura {
+class Window;
+}
+
+namespace aura_shell {
+namespace test {
+
+// A test ActivationDelegate that can be used to track activation changes for
+// an aura::Window.
+class TestActivationDelegate : public aura::ActivationDelegate {
+ public:
+ TestActivationDelegate();
+ explicit TestActivationDelegate(bool activate);
+
+ // Associates this delegate with a Window.
+ void SetWindow(aura::Window* window);
+
+ bool window_was_active() const { return window_was_active_; }
+ void set_activate(bool v) { activate_ = v; }
+ int activated_count() const { return activated_count_; }
+ int lost_active_count() const { return lost_active_count_; }
+ int should_activate_count() const { return should_activate_count_; }
+ void Clear() {
+ activated_count_ = lost_active_count_ = should_activate_count_ = 0;
+ window_was_active_ = false;
+ }
+
+ // Overridden from ActivationDelegate:
+ virtual bool ShouldActivate(aura::Event* event) OVERRIDE;
+ virtual void OnActivated() OVERRIDE;
+ virtual void OnLostActive() OVERRIDE;
+
+ private:
+ aura::Window* window_;
+ bool window_was_active_;
+ bool activate_;
+ int activated_count_;
+ int lost_active_count_;
+ int should_activate_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestActivationDelegate);
+};
+
+} // namespace test
+} // namespace aura_shell
+
+#endif // UI_AURA_SHELL_TEST_TEST_ACTIVATION_DELEGATE_H_
diff --git a/ui/aura_shell/window_util.cc b/ui/aura_shell/window_util.cc
index 68fcab7..82e9875 100644
--- a/ui/aura_shell/window_util.cc
+++ b/ui/aura_shell/window_util.cc
@@ -4,8 +4,11 @@
#include "ui/aura_shell/window_util.h"
-#include "ui/aura/window.h"
+#include "ui/aura/client/activation_client.h"
#include "ui/aura/client/aura_constants.h"
+#include "ui/aura/root_window.h"
+#include "ui/aura/window.h"
+#include "ui/aura_shell/activation_controller.h"
#include "ui/base/ui_base_types.h"
namespace aura_shell {
@@ -15,4 +18,24 @@ bool IsWindowMaximized(aura::Window* window) {
ui::SHOW_STATE_MAXIMIZED;
}
+void ActivateWindow(aura::Window* window) {
+ aura::ActivationClient::GetActivationClient()->ActivateWindow(window);
+}
+
+void DeactivateWindow(aura::Window* window) {
+ aura::ActivationClient::GetActivationClient()->DeactivateWindow(window);
+}
+
+bool IsActiveWindow(aura::Window* window) {
+ return GetActiveWindow() == window;
+}
+
+aura::Window* GetActiveWindow() {
+ return aura::ActivationClient::GetActivationClient()->GetActiveWindow();
+}
+
+aura::Window* GetActivatableWindow(aura::Window* window) {
+ return internal::ActivationController::GetActivatableWindow(window);
+}
+
} // namespace aura_shell
diff --git a/ui/aura_shell/window_util.h b/ui/aura_shell/window_util.h
index 1550510..0c95912 100644
--- a/ui/aura_shell/window_util.h
+++ b/ui/aura_shell/window_util.h
@@ -17,6 +17,19 @@ namespace aura_shell {
// Returns true if |window| is in the maximized state.
AURA_SHELL_EXPORT bool IsWindowMaximized(aura::Window* window);
+// Convenience setters/getters for |aura::kRootWindowActiveWindow|.
+AURA_SHELL_EXPORT void ActivateWindow(aura::Window* window);
+AURA_SHELL_EXPORT void DeactivateWindow(aura::Window* window);
+AURA_SHELL_EXPORT bool IsActiveWindow(aura::Window* window);
+AURA_SHELL_EXPORT aura::Window* GetActiveWindow();
+
+// Retrieves the activatable window for |window|. If |window| is activatable,
+// this will just return it, otherwise it will climb the parent/transient parent
+// chain looking for a window that is activatable, per the ActivationController.
+// If you're looking for a function to get the activatable "top level" window,
+// this is probably what you're looking for.
+AURA_SHELL_EXPORT aura::Window* GetActivatableWindow(aura::Window* window);
+
} // namespace aura_shell
#endif // UI_AURA_SHELL_WINDOW_UTIL_H_
diff --git a/ui/aura_shell/workspace/workspace.cc b/ui/aura_shell/workspace/workspace.cc
index ba25771..be969b8 100644
--- a/ui/aura_shell/workspace/workspace.cc
+++ b/ui/aura_shell/workspace/workspace.cc
@@ -11,6 +11,7 @@
#include "ui/aura/root_window.h"
#include "ui/aura/window.h"
#include "ui/aura_shell/property_util.h"
+#include "ui/aura_shell/window_util.h"
#include "ui/aura_shell/workspace/workspace_manager.h"
#include "ui/base/ui_base_types.h"
#include "ui/gfx/compositor/layer.h"
@@ -95,7 +96,7 @@ bool Workspace::Contains(aura::Window* window) const {
aura::Window* Workspace::FindRotateWindowForLocation(
const gfx::Point& position) {
- aura::Window* active = aura::RootWindow::GetInstance()->active_window();
+ aura::Window* active = aura_shell::GetActiveWindow();
if (GetTotalWindowsWidth() < bounds_.width()) {
// If all windows fit to the width of the workspace, it returns the
// window which contains |position|'s x coordinate.
diff --git a/ui/aura_shell/workspace/workspace_manager_unittest.cc b/ui/aura_shell/workspace/workspace_manager_unittest.cc
index d54fb2d..91e72b5 100644
--- a/ui/aura_shell/workspace/workspace_manager_unittest.cc
+++ b/ui/aura_shell/workspace/workspace_manager_unittest.cc
@@ -10,6 +10,8 @@
#include "ui/aura/test/aura_test_base.h"
#include "ui/aura/test/test_stacking_client.h"
#include "ui/aura/window.h"
+#include "ui/aura_shell/activation_controller.h"
+#include "ui/aura_shell/shell_window_ids.h"
#include "ui/aura_shell/workspace/workspace.h"
#include "ui/aura_shell/workspace/workspace_observer.h"
#include "ui/base/ui_base_types.h"
@@ -77,7 +79,16 @@ namespace internal {
class WorkspaceManagerTestBase : public aura::test::AuraTestBase {
public:
- WorkspaceManagerTestBase() {}
+ WorkspaceManagerTestBase() {
+ aura::test::TestStackingClient* stacking_client =
+ static_cast<aura::test::TestStackingClient*>(
+ aura::RootWindow::GetInstance()->stacking_client());
+ stacking_client->default_container()->set_id(
+ internal::kShellWindowId_DefaultContainer);
+ activation_controller_.reset(new internal::ActivationController);
+ activation_controller_->set_default_container_for_test(
+ stacking_client->default_container());
+ }
virtual ~WorkspaceManagerTestBase() {}
virtual void SetUp() OVERRIDE {
@@ -102,6 +113,8 @@ class WorkspaceManagerTestBase : public aura::test::AuraTestBase {
scoped_ptr<WorkspaceManager> manager_;
private:
+ scoped_ptr<internal::ActivationController> activation_controller_;
+
DISALLOW_COPY_AND_ASSIGN(WorkspaceManagerTestBase);
};
diff --git a/ui/aura_shell/workspace_controller.cc b/ui/aura_shell/workspace_controller.cc
index b8c8bf1..39dbaf1 100644
--- a/ui/aura_shell/workspace_controller.cc
+++ b/ui/aura_shell/workspace_controller.cc
@@ -4,12 +4,14 @@
#include "ui/aura_shell/workspace_controller.h"
+#include "ui/aura/client/aura_constants.h"
#include "ui/aura/root_window.h"
#include "ui/aura/window.h"
#include "ui/aura_shell/default_container_layout_manager.h"
#include "ui/aura_shell/launcher/launcher.h"
#include "ui/aura_shell/launcher/launcher_model.h"
#include "ui/aura_shell/shell.h"
+#include "ui/aura_shell/window_util.h"
#include "ui/aura_shell/workspace/workspace.h"
#include "ui/aura_shell/workspace/workspace_manager.h"
@@ -21,6 +23,7 @@ WorkspaceController::WorkspaceController(aura::Window* viewport)
launcher_model_(NULL),
ignore_move_event_(false) {
workspace_manager_->AddObserver(this);
+ aura::RootWindow::GetInstance()->AddRootWindowObserver(this);
aura::RootWindow::GetInstance()->AddObserver(this);
}
@@ -29,6 +32,7 @@ WorkspaceController::~WorkspaceController() {
if (launcher_model_)
launcher_model_->RemoveObserver(this);
aura::RootWindow::GetInstance()->RemoveObserver(this);
+ aura::RootWindow::GetInstance()->RemoveRootWindowObserver(this);
}
void WorkspaceController::ToggleOverview() {
@@ -48,11 +52,18 @@ void WorkspaceController::OnRootWindowResized(const gfx::Size& new_size) {
workspace_manager_->SetWorkspaceSize(new_size);
}
-void WorkspaceController::OnActiveWindowChanged(aura::Window* active) {
- // FindBy handles NULL.
- Workspace* workspace = workspace_manager_->FindBy(active);
- if (workspace)
- workspace->Activate();
+////////////////////////////////////////////////////////////////////////////////
+// WorkspaceController, aura::WindowObserver overrides:
+
+void WorkspaceController::OnWindowPropertyChanged(aura::Window* window,
+ const char* key,
+ void* old) {
+ if (key == aura::kRootWindowActiveWindow) {
+ // FindBy handles NULL.
+ Workspace* workspace = workspace_manager_->FindBy(GetActiveWindow());
+ if (workspace)
+ workspace->Activate();
+ }
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/ui/aura_shell/workspace_controller.h b/ui/aura_shell/workspace_controller.h
index e41899e..fd9e311 100644
--- a/ui/aura_shell/workspace_controller.h
+++ b/ui/aura_shell/workspace_controller.h
@@ -9,6 +9,7 @@
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "ui/aura/root_window_observer.h"
+#include "ui/aura/window_observer.h"
#include "ui/aura_shell/aura_shell_export.h"
#include "ui/aura_shell/launcher/launcher_model_observer.h"
#include "ui/aura_shell/workspace/workspace_observer.h"
@@ -33,6 +34,7 @@ class WorkspaceManager;
// a move event between Laucher and Workspace.
class AURA_SHELL_EXPORT WorkspaceController :
public aura::RootWindowObserver,
+ public aura::WindowObserver,
public aura_shell::internal::WorkspaceObserver,
public aura_shell::LauncherModelObserver {
public:
@@ -48,9 +50,13 @@ class AURA_SHELL_EXPORT WorkspaceController :
return workspace_manager_.get();
}
- // RootWindowObserver overrides:
+ // aura::RootWindowObserver overrides:
virtual void OnRootWindowResized(const gfx::Size& new_size) OVERRIDE;
- virtual void OnActiveWindowChanged(aura::Window* active) OVERRIDE;
+
+ // aura::WindowObserver overrides:
+ virtual void OnWindowPropertyChanged(aura::Window* window,
+ const char* key,
+ void* old) OVERRIDE;
// WorkspaceObserver overrides:
virtual void WindowMoved(WorkspaceManager* manager,
diff --git a/ui/aura_shell/workspace_controller_unittest.cc b/ui/aura_shell/workspace_controller_unittest.cc
index 7128a40..ab009d2 100644
--- a/ui/aura_shell/workspace_controller_unittest.cc
+++ b/ui/aura_shell/workspace_controller_unittest.cc
@@ -7,6 +7,9 @@
#include "ui/aura/test/aura_test_base.h"
#include "ui/aura/test/test_stacking_client.h"
#include "ui/aura/window.h"
+#include "ui/aura_shell/activation_controller.h"
+#include "ui/aura_shell/shell_window_ids.h"
+#include "ui/aura_shell/window_util.h"
#include "ui/aura_shell/workspace/workspace.h"
#include "ui/aura_shell/workspace/workspace_manager.h"
@@ -23,10 +26,17 @@ class WorkspaceControllerTest : public aura::test::AuraTestBase {
virtual void SetUp() OVERRIDE {
aura::test::AuraTestBase::SetUp();
contents_view_ = GetTestStackingClient()->default_container();
+ // Activatable windows need to be in a container the ActivationController
+ // recognizes.
+ contents_view_->set_id(
+ aura_shell::internal::kShellWindowId_DefaultContainer);
+ activation_controller_.reset(new ActivationController);
+ activation_controller_->set_default_container_for_test(contents_view_);
controller_.reset(new WorkspaceController(contents_view_));
}
virtual void TearDown() OVERRIDE {
+ activation_controller_.reset();
controller_.reset();
aura::test::AuraTestBase::TearDown();
}
@@ -39,7 +49,7 @@ class WorkspaceControllerTest : public aura::test::AuraTestBase {
return window;
}
- aura::Window * contents_view() {
+ aura::Window* contents_view() {
return contents_view_;
}
@@ -52,6 +62,8 @@ class WorkspaceControllerTest : public aura::test::AuraTestBase {
private:
aura::Window* contents_view_;
+ scoped_ptr<ActivationController> activation_controller_;
+
DISALLOW_COPY_AND_ASSIGN(WorkspaceControllerTest);
};
@@ -69,7 +81,7 @@ TEST_F(WorkspaceControllerTest, Overview) {
EXPECT_TRUE(ws2->AddWindowAfter(w2.get(), NULL));
// Activating a window switches the active workspace.
- w2->Activate();
+ aura_shell::ActivateWindow(w2.get());
EXPECT_EQ(ws2, workspace_manager()->GetActiveWorkspace());
// The size of contents_view() is now ws1(500) + ws2(500) + margin(50).
@@ -83,7 +95,7 @@ TEST_F(WorkspaceControllerTest, Overview) {
// Activating window w1 switches the active window and
// the mode back to normal mode.
- w1->Activate();
+ aura_shell::ActivateWindow(w1.get());
EXPECT_EQ(ws1, workspace_manager()->GetActiveWorkspace());
EXPECT_FALSE(workspace_manager()->is_overview());
diff --git a/ui/views/test/views_test_base.cc b/ui/views/test/views_test_base.cc
index e57b2d6..4ba41cf 100644
--- a/ui/views/test/views_test_base.cc
+++ b/ui/views/test/views_test_base.cc
@@ -10,6 +10,7 @@
#if defined(USE_AURA)
#include "ui/aura/root_window.h"
+#include "ui/aura/test/test_activation_client.h"
#include "ui/aura/test/test_stacking_client.h"
#endif
@@ -22,6 +23,7 @@ ViewsTestBase::ViewsTestBase()
OleInitialize(NULL);
#endif
#if defined(USE_AURA)
+ test_activation_client_.reset(new aura::test::TestActivationClient);
new aura::test::TestStackingClient;
#endif
}
diff --git a/ui/views/test/views_test_base.h b/ui/views/test/views_test_base.h
index eed6889..c9c674b 100644
--- a/ui/views/test/views_test_base.h
+++ b/ui/views/test/views_test_base.h
@@ -11,6 +11,12 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/views/test/test_views_delegate.h"
+namespace aura {
+namespace test {
+class TestActivationClient;
+}
+}
+
namespace views {
class TestViewsDelegate;
@@ -40,6 +46,9 @@ class ViewsTestBase : public testing::Test {
private:
MessageLoopForUI message_loop_;
scoped_ptr<TestViewsDelegate> views_delegate_;
+#if defined(USE_AURA)
+ scoped_ptr<aura::test::TestActivationClient> test_activation_client_;
+#endif
bool setup_called_;
bool teardown_called_;
diff --git a/ui/views/widget/native_widget_aura.cc b/ui/views/widget/native_widget_aura.cc
index 4ad5826..ac87620 100644
--- a/ui/views/widget/native_widget_aura.cc
+++ b/ui/views/widget/native_widget_aura.cc
@@ -6,13 +6,14 @@
#include "base/bind.h"
#include "base/string_util.h"
+#include "ui/aura/client/activation_client.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/drag_drop_client.h"
#include "ui/aura/client/shadow_types.h"
#include "ui/aura/event.h"
#include "ui/aura/root_window.h"
-#include "ui/aura/root_window_observer.h"
#include "ui/aura/window.h"
+#include "ui/aura/window_observer.h"
#include "ui/aura/window_types.h"
#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/base/ui_base_types.h"
@@ -76,20 +77,23 @@ void NotifyLocaleChangedInternal(aura::Window* window) {
// Used when SetInactiveRenderingDisabled() is invoked to track when active
// status changes in such a way that we should enable inactive rendering.
-class NativeWidgetAura::RootWindowObserverImpl
- : public aura::RootWindowObserver {
+class NativeWidgetAura::ActiveWindowObserver : public aura::WindowObserver {
public:
- explicit RootWindowObserverImpl(NativeWidgetAura* host)
- : host_(host) {
+ explicit ActiveWindowObserver(NativeWidgetAura* host) : host_(host) {
aura::RootWindow::GetInstance()->AddObserver(this);
}
-
- virtual ~RootWindowObserverImpl() {
+ virtual ~ActiveWindowObserver() {
aura::RootWindow::GetInstance()->RemoveObserver(this);
}
- // RootWindowObserver overrides:
- virtual void OnActiveWindowChanged(aura::Window* active) OVERRIDE {
+ // Overridden from aura::WindowObserver:
+ virtual void OnWindowPropertyChanged(aura::Window* window,
+ const char* key,
+ void* old) OVERRIDE {
+ if (key != aura::kRootWindowActiveWindow)
+ return;
+ aura::Window* active =
+ aura::ActivationClient::GetActivationClient()->GetActiveWindow();
if (!active || (active != host_->window_ &&
active->transient_parent() != host_->window_)) {
host_->delegate_->EnableInactiveRendering();
@@ -99,7 +103,7 @@ class NativeWidgetAura::RootWindowObserverImpl
private:
NativeWidgetAura* host_;
- DISALLOW_COPY_AND_ASSIGN(RootWindowObserverImpl);
+ DISALLOW_COPY_AND_ASSIGN(ActiveWindowObserver);
};
////////////////////////////////////////////////////////////////////////////////
@@ -181,6 +185,8 @@ void NativeWidgetAura::InitNativeWidget(const Widget::InitParams& params) {
static_cast<aura::WindowDragDropDelegate*>(this));
}
+ aura::ActivationDelegate::SetActivationDelegate(window_, this);
+
if (window_type == Widget::InitParams::TYPE_MENU ||
window_type == Widget::InitParams::TYPE_TOOLTIP)
window_->SetIntProperty(aura::kShadowTypeKey,
@@ -425,7 +431,7 @@ void NativeWidgetAura::ShowWithWindowState(ui::WindowShowState state) {
window_->Show();
if (can_activate_ && (state != ui::SHOW_STATE_INACTIVE ||
!GetWidget()->SetInitialFocus())) {
- window_->Activate();
+ Activate();
}
}
@@ -434,15 +440,16 @@ bool NativeWidgetAura::IsVisible() const {
}
void NativeWidgetAura::Activate() {
- window_->Activate();
+ aura::ActivationClient::GetActivationClient()->ActivateWindow(window_);
}
void NativeWidgetAura::Deactivate() {
- window_->Deactivate();
+ aura::ActivationClient::GetActivationClient()->DeactivateWindow(window_);
}
bool NativeWidgetAura::IsActive() const {
- return aura::RootWindow::GetInstance()->active_window() == window_;
+ return aura::ActivationClient::GetActivationClient()->GetActiveWindow() ==
+ window_;
}
void NativeWidgetAura::SetAlwaysOnTop(bool on_top) {
@@ -532,9 +539,9 @@ gfx::Rect NativeWidgetAura::GetWorkAreaBoundsInScreen() const {
void NativeWidgetAura::SetInactiveRenderingDisabled(bool value) {
if (!value)
- root_window_observer_.reset();
+ active_window_observer_.reset();
else
- root_window_observer_.reset(new RootWindowObserverImpl(this));
+ active_window_observer_.reset(new ActiveWindowObserver(this));
}
////////////////////////////////////////////////////////////////////////////////
@@ -629,22 +636,6 @@ bool NativeWidgetAura::CanFocus() {
return true;
}
-bool NativeWidgetAura::ShouldActivate(aura::Event* event) {
- return can_activate_;
-}
-
-void NativeWidgetAura::OnActivated() {
- delegate_->OnNativeWidgetActivationChanged(true);
- if (IsVisible() && GetWidget()->non_client_view())
- GetWidget()->non_client_view()->SchedulePaint();
-}
-
-void NativeWidgetAura::OnLostActive() {
- delegate_->OnNativeWidgetActivationChanged(false);
- if (IsVisible() && GetWidget()->non_client_view())
- GetWidget()->non_client_view()->SchedulePaint();
-}
-
void NativeWidgetAura::OnCaptureLost() {
delegate_->OnMouseCaptureLost();
}
@@ -673,6 +664,28 @@ void NativeWidgetAura::OnWindowVisibilityChanged(bool visible) {
delegate_->OnNativeWidgetVisibilityChanged(visible);
}
+////////////////////////////////////////////////////////////////////////////////
+// NativeWidgetAura, aura::ActivationDelegate implementation:
+
+bool NativeWidgetAura::ShouldActivate(aura::Event* event) {
+ return can_activate_;
+}
+
+void NativeWidgetAura::OnActivated() {
+ delegate_->OnNativeWidgetActivationChanged(true);
+ if (IsVisible() && GetWidget()->non_client_view())
+ GetWidget()->non_client_view()->SchedulePaint();
+}
+
+void NativeWidgetAura::OnLostActive() {
+ delegate_->OnNativeWidgetActivationChanged(false);
+ if (IsVisible() && GetWidget()->non_client_view())
+ GetWidget()->non_client_view()->SchedulePaint();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeWidgetAura, aura::WindowDragDropDelegate implementation:
+
void NativeWidgetAura::OnDragEntered(const aura::DropTargetEvent& event) {
DCHECK(drop_helper_.get() != NULL);
drop_helper_->OnDragOver(event.data(), event.location(),
diff --git a/ui/views/widget/native_widget_aura.h b/ui/views/widget/native_widget_aura.h
index aedfeb6..e4a1a12 100644
--- a/ui/views/widget/native_widget_aura.h
+++ b/ui/views/widget/native_widget_aura.h
@@ -8,6 +8,7 @@
#include "base/memory/scoped_vector.h"
#include "base/memory/weak_ptr.h"
+#include "ui/aura/client/activation_delegate.h"
#include "ui/aura/client/window_drag_drop_delegate.h"
#include "ui/aura/window_delegate.h"
#include "ui/base/events.h"
@@ -28,6 +29,7 @@ class TooltipManagerAura;
class VIEWS_EXPORT NativeWidgetAura : public internal::NativeWidgetPrivate,
public aura::WindowDelegate,
+ public aura::ActivationDelegate,
public aura::WindowDragDropDelegate {
public:
explicit NativeWidgetAura(internal::NativeWidgetDelegate* delegate);
@@ -132,15 +134,17 @@ class VIEWS_EXPORT NativeWidgetAura : public internal::NativeWidgetPrivate,
virtual bool OnMouseEvent(aura::MouseEvent* event) OVERRIDE;
virtual ui::TouchStatus OnTouchEvent(aura::TouchEvent* event) OVERRIDE;
virtual bool CanFocus() OVERRIDE;
- virtual bool ShouldActivate(aura::Event* event) OVERRIDE;
- virtual void OnActivated() OVERRIDE;
- virtual void OnLostActive() OVERRIDE;
virtual void OnCaptureLost() OVERRIDE;
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
virtual void OnWindowDestroying() OVERRIDE;
virtual void OnWindowDestroyed() OVERRIDE;
virtual void OnWindowVisibilityChanged(bool visible) OVERRIDE;
+ // Overridden from aura::ActivationDelegate:
+ virtual bool ShouldActivate(aura::Event* event) OVERRIDE;
+ virtual void OnActivated() OVERRIDE;
+ virtual void OnLostActive() OVERRIDE;
+
// Overridden from aura::WindowDragDropDelegate:
virtual void OnDragEntered(const aura::DropTargetEvent& event) OVERRIDE;
virtual int OnDragUpdated(const aura::DropTargetEvent& event) OVERRIDE;
@@ -151,7 +155,7 @@ class VIEWS_EXPORT NativeWidgetAura : public internal::NativeWidgetPrivate,
internal::NativeWidgetDelegate* delegate() { return delegate_; }
private:
- class RootWindowObserverImpl;
+ class ActiveWindowObserver;
internal::NativeWidgetDelegate* delegate_;
@@ -171,7 +175,7 @@ class VIEWS_EXPORT NativeWidgetAura : public internal::NativeWidgetPrivate,
scoped_ptr<TooltipManagerAura> tooltip_manager_;
- scoped_ptr<RootWindowObserverImpl> root_window_observer_;
+ scoped_ptr<ActiveWindowObserver> active_window_observer_;
scoped_ptr<DropHelper> drop_helper_;