Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "ash/wm/window_cycle_list.h" | |
| 6 | |
| 7 #include "ash/shell.h" | |
| 8 #include "ash/wm/mru_window_tracker.h" | |
| 9 #include "ash/wm/window_animations.h" | |
| 10 #include "ash/wm/window_state.h" | |
| 11 #include "ash/wm/window_util.h" | |
| 12 #include "ui/aura/window.h" | |
| 13 | |
| 14 namespace ash { | |
| 15 | |
| 16 // Returns the window immediately below |window| in the current container. | |
| 17 aura::Window* GetWindowBelow(aura::Window* window) { | |
| 18 aura::Window* parent = window->parent(); | |
| 19 if (!parent) | |
| 20 return NULL; | |
| 21 aura::Window* below = NULL; | |
| 22 for (aura::Window::Windows::const_iterator iter = parent->children().begin(); | |
| 23 iter != parent->children().end(); ++iter) { | |
| 24 if (*iter == window) | |
| 25 return below; | |
| 26 below = *iter; | |
| 27 } | |
| 28 NOTREACHED(); | |
| 29 return NULL; | |
| 30 } | |
| 31 | |
| 32 // This class restores and moves a window to the front of the stacking order for | |
| 33 // the duration of the class's scope. | |
| 34 class ScopedShowWindow : public aura::WindowObserver { | |
| 35 public: | |
| 36 ScopedShowWindow(); | |
| 37 virtual ~ScopedShowWindow(); | |
| 38 | |
| 39 // Show |window| at the top of the stacking order. | |
| 40 void Show(aura::Window* window); | |
| 41 | |
| 42 // Cancel restoring the window on going out of scope. | |
| 43 void CancelRestore(); | |
| 44 | |
| 45 aura::Window* window() { return window_; } | |
| 46 | |
| 47 // aura::WindowObserver: | |
| 48 virtual void OnWillRemoveWindow(aura::Window* window) OVERRIDE; | |
| 49 | |
| 50 private: | |
| 51 // The window being shown. | |
| 52 aura::Window* window_; | |
| 53 | |
| 54 // The window immediately below where window_ belongs. | |
| 55 aura::Window* stack_window_above_; | |
| 56 | |
| 57 // If true, minimize window_ on going out of scope. | |
| 58 bool minimized_; | |
| 59 | |
| 60 DISALLOW_COPY_AND_ASSIGN(ScopedShowWindow); | |
| 61 }; | |
| 62 | |
| 63 ScopedShowWindow::ScopedShowWindow() | |
| 64 : window_(NULL), | |
| 65 stack_window_above_(NULL), | |
| 66 minimized_(false) { | |
| 67 } | |
| 68 | |
| 69 void ScopedShowWindow::Show(aura::Window* window) { | |
| 70 DCHECK(!window_); | |
| 71 window_ = window; | |
| 72 stack_window_above_ = GetWindowBelow(window); | |
| 73 minimized_ = wm::GetWindowState(window)->IsMinimized(); | |
| 74 window_->parent()->AddObserver(this); | |
| 75 window_->Show(); | |
| 76 wm::GetWindowState(window_)->Activate(); | |
| 77 } | |
| 78 | |
| 79 ScopedShowWindow::~ScopedShowWindow() { | |
| 80 if (window_) { | |
| 81 window_->parent()->RemoveObserver(this); | |
| 82 | |
| 83 // Restore window's stacking position. | |
| 84 if (stack_window_above_) | |
| 85 window_->parent()->StackChildAbove(window_, stack_window_above_); | |
| 86 else | |
| 87 window_->parent()->StackChildAtBottom(window_); | |
| 88 | |
| 89 // Restore minimized state. | |
| 90 if (minimized_) | |
| 91 wm::GetWindowState(window_)->Minimize(); | |
| 92 } | |
| 93 } | |
| 94 | |
| 95 void ScopedShowWindow::CancelRestore() { | |
| 96 if (!window_) | |
| 97 return; | |
| 98 window_->parent()->RemoveObserver(this); | |
| 99 window_ = stack_window_above_ = NULL; | |
| 100 } | |
| 101 | |
| 102 void ScopedShowWindow::OnWillRemoveWindow(aura::Window* window) { | |
| 103 if (window == window_) { | |
| 104 CancelRestore(); | |
| 105 } else if (window == stack_window_above_) { | |
| 106 // If the window this window was above is removed, use the next window down | |
| 107 // as the restore marker. | |
| 108 stack_window_above_ = GetWindowBelow(stack_window_above_); | |
| 109 } | |
| 110 } | |
| 111 | |
| 112 WindowCycleList::WindowCycleList(const WindowList& windows) | |
| 113 : windows_(windows), | |
| 114 current_index_(-1) { | |
| 115 ash::Shell::GetInstance()->mru_window_tracker()->SetIgnoreActivations(true); | |
| 116 // Locate the currently active window in the list to use as our start point. | |
| 117 aura::Window* active_window = wm::GetActiveWindow(); | |
| 118 | |
| 119 // The active window may not be in the cycle list, which is expected if there | |
| 120 // are additional modal windows on the screen. | |
| 121 current_index_ = GetWindowIndex(active_window); | |
| 122 | |
| 123 for (WindowList::const_iterator i = windows_.begin(); i != windows_.end(); | |
| 124 ++i) { | |
| 125 (*i)->AddObserver(this); | |
| 126 } | |
| 127 } | |
| 128 | |
| 129 WindowCycleList::~WindowCycleList() { | |
| 130 ash::Shell::GetInstance()->mru_window_tracker()->SetIgnoreActivations(false); | |
| 131 for (WindowList::const_iterator i = windows_.begin(); i != windows_.end(); | |
| 132 ++i) { | |
| 133 (*i)->RemoveObserver(this); | |
| 134 } | |
| 135 if (showing_window_) | |
| 136 showing_window_->CancelRestore(); | |
| 137 } | |
| 138 | |
| 139 void WindowCycleList::Step(Direction direction) { | |
| 140 if (windows_.empty()) | |
| 141 return; | |
| 142 | |
| 143 if (current_index_ == -1) { | |
| 144 // We weren't able to find our active window in the shell delegate's | |
|
tdanderson
2014/05/01 18:51:39
This worries me a little bit. I feel that a precon
Nina
2014/05/01 20:41:16
Done.
| |
| 145 // provided window list. Just switch to the first (or last) one. | |
| 146 current_index_ = (direction == FORWARD ? 0 : windows_.size() - 1); | |
|
tdanderson
2014/05/01 18:51:39
No () needed
Nina
2014/05/01 20:41:16
Done.
| |
| 147 } else { | |
| 148 // When there is only one window, we should give a feedback to user. | |
|
tdanderson
2014/05/01 18:51:39
Double-check with the logs (or Rob if you can't fi
Nina
2014/05/01 20:41:16
Could not find anything on the logs, I asked Rob a
tdanderson
2014/05/01 21:58:33
I don't think that is necessary. If Rob is OK with
| |
| 149 if (windows_.size() == 1) { | |
| 150 ::wm::AnimateWindow(windows_[0], | |
| 151 ::wm::WINDOW_ANIMATION_TYPE_BOUNCE); | |
|
tdanderson
2014/05/01 18:51:39
Spacing
Nina
2014/05/01 20:41:16
Done.
| |
| 152 return; | |
| 153 } | |
| 154 // We're in a valid cycle, so step forward or backward. | |
| 155 current_index_ += (direction == FORWARD ? 1 : -1); | |
|
tdanderson
2014/05/01 18:51:39
No ()
Nina
2014/05/01 20:41:16
Done.
| |
| 156 } | |
| 157 // Wrap to window list size. | |
| 158 current_index_ = (current_index_ + windows_.size()) % windows_.size(); | |
| 159 DCHECK(windows_[current_index_]); | |
| 160 // Make sure the next window is visible. | |
| 161 showing_window_.reset(new ScopedShowWindow); | |
| 162 showing_window_->Show(windows_[current_index_]); | |
| 163 } | |
| 164 | |
| 165 int WindowCycleList::GetWindowIndex(aura::Window* window) { | |
| 166 WindowList::const_iterator it = | |
| 167 std::find(windows_.begin(), windows_.end(), window); | |
| 168 if (it == windows_.end()) | |
| 169 return -1; // Not found. | |
| 170 return it - windows_.begin(); | |
| 171 } | |
| 172 | |
| 173 void WindowCycleList::OnWindowDestroyed(aura::Window* window) { | |
| 174 window->RemoveObserver(this); | |
| 175 | |
| 176 WindowList::iterator i = std::find(windows_.begin(), windows_.end(), window); | |
| 177 DCHECK(i != windows_.end()); | |
| 178 int removed_index = static_cast<int>(i - windows_.begin()); | |
| 179 windows_.erase(i); | |
| 180 if (current_index_ > removed_index) | |
|
tdanderson
2014/05/01 18:51:39
combine lines 180-183 into a single check
Nina
2014/05/01 20:41:16
Done.
| |
| 181 current_index_--; | |
| 182 else if (current_index_ == static_cast<int>(windows_.size())) | |
| 183 current_index_--; | |
| 184 } | |
| 185 | |
| 186 } // namespace ash | |
| OLD | NEW |