Index: ash/wm/window_cycle_controller.cc |
diff --git a/ash/wm/window_cycle_controller.cc b/ash/wm/window_cycle_controller.cc |
index f48ee76afa8f92f3d4aca34ba119b474c003141b..81a72430eaa4f52763990cc71d9f36cc7d2ed42f 100644 |
--- a/ash/wm/window_cycle_controller.cc |
+++ b/ash/wm/window_cycle_controller.cc |
@@ -9,6 +9,7 @@ |
#include "ash/shell.h" |
#include "ash/shell_delegate.h" |
#include "ash/shell_window_ids.h" |
+#include "ash/wm/activation_controller.h" |
#include "ash/wm/window_cycle_list.h" |
#include "ash/wm/window_util.h" |
#include "ui/aura/event.h" |
@@ -19,6 +20,12 @@ namespace ash { |
namespace { |
+// List of containers whose children we will cycle through. |
+const int kContainerIds[] = { |
+ internal::kShellWindowId_DefaultContainer, |
+ internal::kShellWindowId_AlwaysOnTopContainer |
+}; |
+ |
// Filter to watch for the termination of a keyboard gesture to cycle through |
// multiple windows. |
class WindowCycleEventFilter : public aura::EventFilter { |
@@ -82,10 +89,12 @@ ui::GestureStatus WindowCycleEventFilter::PreHandleGestureEvent( |
////////////////////////////////////////////////////////////////////////////// |
// WindowCycleController, public: |
-WindowCycleController::WindowCycleController() { |
+WindowCycleController::WindowCycleController() : mru_ignore_(false) { |
+ Shell::GetInstance()->activation_controller()->AddObserver(this); |
} |
WindowCycleController::~WindowCycleController() { |
+ Shell::GetInstance()->activation_controller()->RemoveObserver(this); |
StopCycling(); |
sky
2012/07/24 03:53:31
Doesn't this need to remove observers from all the
Zachary Kuznia
2012/07/30 07:49:48
No. The containers get the OnWindowDestroying not
|
} |
@@ -104,6 +113,7 @@ void WindowCycleController::HandleCycleWindow(Direction direction, |
if (is_alt_down) { |
if (!IsCycling()) { |
+ mru_ignore_ = true; |
// This is the start of an alt-tab cycle through multiple windows, so |
// listen for the alt key being released to stop cycling. |
StartCycling(); |
sky
2012/07/24 03:53:31
Wouldn't it make more sense to set mru_ignore_ in
Zachary Kuznia
2012/07/30 07:49:48
Done.
|
@@ -123,10 +133,19 @@ void WindowCycleController::HandleCycleWindow(Direction direction, |
void WindowCycleController::AltKeyReleased() { |
StopCycling(); |
+ |
+ // Add the currently focused window to the MRU list, and stop ignoring |
+ // activations. |
+ mru_ignore_ = false; |
+ aura::Window* active_window = wm::GetActiveWindow(); |
+ mru_windows_.remove(active_window); |
+ mru_windows_.push_front(active_window); |
} |
// static |
-std::vector<aura::Window*> WindowCycleController::BuildWindowList() { |
+std::vector<aura::Window*> WindowCycleController::BuildWindowList( |
+ std::list<aura::Window*>* mru_windows) { |
sky
2012/07/24 03:53:31
const std::list&
Zachary Kuznia
2012/07/30 07:49:48
Changed to const. It needs to be a pointer, thoug
|
+ |
sky
2012/07/24 03:53:31
remove newline
Zachary Kuznia
2012/07/30 07:49:48
Done.
|
WindowCycleList::WindowList windows; |
Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); |
@@ -134,19 +153,20 @@ std::vector<aura::Window*> WindowCycleController::BuildWindowList() { |
iter != root_windows.end(); ++iter) { |
if (*iter == Shell::GetActiveRootWindow()) |
continue; |
- aura::Window* default_container = Shell::GetContainer( |
- *iter, internal::kShellWindowId_DefaultContainer); |
- WindowCycleList::WindowList children = default_container->children(); |
- windows.insert(windows.end(), children.begin(), children.end()); |
+ for (size_t i = 0; i < arraysize(kContainerIds); ++i) { |
+ aura::Window* container = Shell::GetContainer(*iter, kContainerIds[i]); |
+ WindowCycleList::WindowList children = container->children(); |
+ windows.insert(windows.end(), children.begin(), children.end()); |
+ } |
} |
- // Add windows in the active root windows last so that the topmost window |
- // in the active root window becomes the front of the list. |
- aura::Window* default_container = Shell::GetContainer( |
- Shell::GetActiveRootWindow(), |
- internal::kShellWindowId_DefaultContainer); |
- WindowCycleList::WindowList children = default_container->children(); |
- windows.insert(windows.end(), children.begin(), children.end()); |
+ for (size_t i = 0; i < arraysize(kContainerIds); ++i) { |
+ aura::Window* container = |
+ Shell::GetContainer(Shell::GetActiveRootWindow(), kContainerIds[i]); |
+ |
+ WindowCycleList::WindowList children = container->children(); |
+ windows.insert(windows.end(), children.begin(), children.end()); |
+ } |
// Removes unfocusable windows. |
WindowCycleList::WindowList::iterator last = |
@@ -155,16 +175,40 @@ std::vector<aura::Window*> WindowCycleController::BuildWindowList() { |
windows.end(), |
std::not1(std::ptr_fun(ash::wm::CanActivateWindow))); |
windows.erase(last, windows.end()); |
+ |
+ // Put the windows in the mru_windows list at the head, if it's available. |
sky
2012/07/24 03:53:31
Document why this uses a reverse iterator.
Zachary Kuznia
2012/07/30 07:49:48
Done.
|
+ if (mru_windows) { |
+ for (std::list<aura::Window*>::const_reverse_iterator ix = |
+ mru_windows->rbegin(); |
+ ix != mru_windows->rend(); ++ix) { |
+ WindowCycleList::WindowList::iterator window = |
+ std::find(windows.begin(), windows.end(), *ix); |
+ if (window != windows.end()) { |
+ windows.erase(window); |
+ windows.push_back(*ix); |
+ } |
+ } |
+ } |
+ |
// Window cycling expects the topmost window at the front of the list. |
std::reverse(windows.begin(), windows.end()); |
+ |
return windows; |
} |
+void WindowCycleController::OnRootWindowAdded(aura::RootWindow* root_window) { |
+ for (size_t i = 0; i < arraysize(kContainerIds); ++i) { |
+ aura::Window* container = |
+ Shell::GetContainer(root_window, kContainerIds[i]); |
+ container->AddObserver(this); |
+ } |
+} |
+ |
////////////////////////////////////////////////////////////////////////////// |
// WindowCycleController, private: |
void WindowCycleController::StartCycling() { |
- windows_.reset(new WindowCycleList(BuildWindowList())); |
+ windows_.reset(new WindowCycleList(BuildWindowList(&mru_windows_))); |
} |
void WindowCycleController::Step(Direction direction) { |
@@ -187,4 +231,35 @@ void WindowCycleController::InstallEventFilter() { |
Shell::GetInstance()->AddEnvEventFilter(event_filter_.get()); |
} |
+void WindowCycleController::OnWindowActivated(aura::Window* active, |
+ aura::Window* old_active) { |
+ if (active) { |
+ if (!active->parent()) |
sky
2012/07/24 03:53:31
This code would be easier to read if you made a fu
Zachary Kuznia
2012/07/30 07:49:48
Done.
|
+ return; |
+ |
+ bool ignore = true; |
+ for (size_t i = 0; i < arraysize(kContainerIds); ++i) { |
+ if (active->parent()->id() == kContainerIds[i]) { |
+ ignore = false; |
+ break; |
+ } |
+ } |
+ if (ignore) |
+ return; |
+ |
+ if (!mru_ignore_) { |
sky
2012/07/24 03:53:31
Move this check early on.
Zachary Kuznia
2012/07/30 07:49:48
Done.
|
+ mru_windows_.remove(active); |
+ mru_windows_.push_front(active); |
+ } |
+ } |
+} |
+ |
+void WindowCycleController::OnWillRemoveWindow(aura::Window* window) { |
+ mru_windows_.remove(window); |
+} |
+ |
+void WindowCycleController::OnWindowDestroying(aura::Window* window) { |
+ window->RemoveObserver(this); |
+} |
+ |
} // namespace ash |