Home | History | Annotate | Download | only in corewm
      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 "ui/views/corewm/focus_controller.h"
      6 
      7 #include "base/auto_reset.h"
      8 #include "ui/aura/client/activation_change_observer.h"
      9 #include "ui/aura/client/aura_constants.h"
     10 #include "ui/aura/client/capture_client.h"
     11 #include "ui/aura/client/focus_change_observer.h"
     12 #include "ui/aura/env.h"
     13 #include "ui/base/events/event.h"
     14 #include "ui/views/corewm/focus_rules.h"
     15 
     16 namespace views {
     17 namespace corewm {
     18 namespace {
     19 
     20 // When a modal window is activated, we bring its entire transient parent chain
     21 // to the front. This function must be called before the modal transient is
     22 // stacked at the top to ensure correct stacking order.
     23 void StackTransientParentsBelowModalWindow(aura::Window* window) {
     24   if (window->GetProperty(aura::client::kModalKey) != ui::MODAL_TYPE_WINDOW)
     25     return;
     26 
     27   aura::Window* transient_parent = window->transient_parent();
     28   while (transient_parent) {
     29     transient_parent->parent()->StackChildAtTop(transient_parent);
     30     transient_parent = transient_parent->transient_parent();
     31   }
     32 }
     33 
     34 // Stack's |window|'s layer above |relative_to|'s layer.
     35 void StackWindowLayerAbove(aura::Window* window, aura::Window* relative_to) {
     36   // Stack |window| above the last transient child of |relative_to| that shares
     37   // the same parent.
     38   const aura::Window::Windows& window_transients(
     39       relative_to->transient_children());
     40   for (aura::Window::Windows::const_iterator i = window_transients.begin();
     41        i != window_transients.end(); ++i) {
     42     aura::Window* transient = *i;
     43     if (transient->parent() == relative_to->parent())
     44       relative_to = transient;
     45   }
     46   if (window != relative_to) {
     47     window->layer()->parent()->StackAbove(window->layer(),
     48                                           relative_to->layer());
     49   }
     50 }
     51 
     52 }  // namespace
     53 
     54 ////////////////////////////////////////////////////////////////////////////////
     55 // FocusController, public:
     56 
     57 FocusController::FocusController(FocusRules* rules)
     58     : active_window_(NULL),
     59       focused_window_(NULL),
     60       updating_focus_(false),
     61       updating_activation_(false),
     62       rules_(rules),
     63       observer_manager_(this) {
     64   DCHECK(rules);
     65 }
     66 
     67 FocusController::~FocusController() {
     68 }
     69 
     70 ////////////////////////////////////////////////////////////////////////////////
     71 // FocusController, aura::client::ActivationClient implementation:
     72 
     73 void FocusController::AddObserver(
     74     aura::client::ActivationChangeObserver* observer) {
     75   activation_observers_.AddObserver(observer);
     76 }
     77 
     78 void FocusController::RemoveObserver(
     79     aura::client::ActivationChangeObserver* observer) {
     80   activation_observers_.RemoveObserver(observer);
     81 }
     82 
     83 void FocusController::ActivateWindow(aura::Window* window) {
     84   FocusWindow(window);
     85 }
     86 
     87 void FocusController::DeactivateWindow(aura::Window* window) {
     88   if (window)
     89     FocusWindow(rules_->GetNextActivatableWindow(window));
     90 }
     91 
     92 aura::Window* FocusController::GetActiveWindow() {
     93   return active_window_;
     94 }
     95 
     96 aura::Window* FocusController::GetActivatableWindow(aura::Window* window) {
     97   return rules_->GetActivatableWindow(window);
     98 }
     99 
    100 aura::Window* FocusController::GetToplevelWindow(aura::Window* window) {
    101   return rules_->GetToplevelWindow(window);
    102 }
    103 
    104 bool FocusController::OnWillFocusWindow(aura::Window* window,
    105                                         const ui::Event* event) {
    106   NOTREACHED();
    107   return false;
    108 }
    109 
    110 bool FocusController::CanActivateWindow(aura::Window* window) const {
    111   return rules_->CanActivateWindow(window);
    112 }
    113 
    114 ////////////////////////////////////////////////////////////////////////////////
    115 // FocusController, aura::client::FocusClient implementation:
    116 
    117 void FocusController::AddObserver(
    118     aura::client::FocusChangeObserver* observer) {
    119   focus_observers_.AddObserver(observer);
    120 }
    121 
    122 void FocusController::RemoveObserver(
    123     aura::client::FocusChangeObserver* observer) {
    124   focus_observers_.RemoveObserver(observer);
    125 }
    126 
    127 void FocusController::FocusWindow(aura::Window* window) {
    128   if (window &&
    129       (window->Contains(focused_window_) || window->Contains(active_window_))) {
    130     return;
    131   }
    132 
    133   // We should not be messing with the focus if the window has capture.
    134   if (window && (aura::client::GetCaptureWindow(window) == window))
    135     return;
    136 
    137   // Focusing a window also activates its containing activatable window. Note
    138   // that the rules could redirect activation activation and/or focus.
    139   aura::Window* focusable = rules_->GetFocusableWindow(window);
    140   aura::Window* activatable =
    141       focusable ? rules_->GetActivatableWindow(focusable) : NULL;
    142 
    143   // We need valid focusable/activatable windows in the event we're not clearing
    144   // focus. "Clearing focus" is inferred by whether or not |window| passed to
    145   // this function is non-NULL.
    146   if (window && (!focusable || !activatable))
    147     return;
    148   DCHECK((focusable && activatable) || !window);
    149 
    150   // Activation change observers may change the focused window. If this happens
    151   // we must not adjust the focus below since this will clobber that change.
    152   aura::Window* last_focused_window = focused_window_;
    153   if (!updating_activation_)
    154     SetActiveWindow(window, activatable);
    155 
    156   // If the window's ActivationChangeObserver shifted focus to a valid window,
    157   // we don't want to focus the window we thought would be focused by default.
    158   bool activation_changed_focus = last_focused_window != focused_window_;
    159   if (!updating_focus_ && (!activation_changed_focus || !focused_window_)) {
    160     if (active_window_ && focusable)
    161       DCHECK(active_window_->Contains(focusable));
    162     SetFocusedWindow(focusable);
    163   }
    164 }
    165 
    166 void FocusController::ResetFocusWithinActiveWindow(aura::Window* window) {
    167   DCHECK(window);
    168   if (!active_window_)
    169     return;
    170   if (!active_window_->Contains(window))
    171     return;
    172   SetFocusedWindow(window);
    173 }
    174 
    175 aura::Window* FocusController::GetFocusedWindow() {
    176   return focused_window_;
    177 }
    178 
    179 void FocusController::OnWindowHiddenInRootWindow(
    180     aura::Window* window,
    181     aura::RootWindow* root_window,
    182     bool destroyed) {
    183   //NOTREACHED();
    184   // This method is only for compat with aura::FocusManager. It should not be
    185   // needed in the new FocusController.
    186 }
    187 
    188 ////////////////////////////////////////////////////////////////////////////////
    189 // FocusController, ui::EventHandler implementation:
    190 void FocusController::OnKeyEvent(ui::KeyEvent* event) {
    191 }
    192 
    193 void FocusController::OnMouseEvent(ui::MouseEvent* event) {
    194   if (event->type() == ui::ET_MOUSE_PRESSED)
    195     WindowFocusedFromInputEvent(static_cast<aura::Window*>(event->target()));
    196 }
    197 
    198 void FocusController::OnScrollEvent(ui::ScrollEvent* event) {
    199 }
    200 
    201 void FocusController::OnTouchEvent(ui::TouchEvent* event) {
    202 }
    203 
    204 void FocusController::OnGestureEvent(ui::GestureEvent* event) {
    205   if (event->type() == ui::ET_GESTURE_BEGIN &&
    206       event->details().touch_points() == 1) {
    207     WindowFocusedFromInputEvent(static_cast<aura::Window*>(event->target()));
    208   }
    209 }
    210 
    211 ////////////////////////////////////////////////////////////////////////////////
    212 // FocusController, aura::WindowObserver implementation:
    213 
    214 void FocusController::OnWindowVisibilityChanged(aura::Window* window,
    215                                                 bool visible) {
    216   if (!visible) {
    217     WindowLostFocusFromDispositionChange(window, window->parent());
    218     // Despite the focus change, we need to keep the window being hidden
    219     // stacked above the new window so it stays open on top as it animates away.
    220     aura::Window* next_window = GetActiveWindow();
    221     if (next_window && next_window->parent() == window->parent())
    222       StackWindowLayerAbove(window, next_window);
    223   }
    224 }
    225 
    226 void FocusController::OnWindowDestroying(aura::Window* window) {
    227   WindowLostFocusFromDispositionChange(window, window->parent());
    228 }
    229 
    230 void FocusController::OnWindowHierarchyChanging(
    231     const HierarchyChangeParams& params) {
    232   if (params.receiver == active_window_ &&
    233       params.target->Contains(params.receiver) && (!params.new_parent ||
    234       aura::client::GetFocusClient(params.new_parent) !=
    235           aura::client::GetFocusClient(params.receiver))) {
    236     WindowLostFocusFromDispositionChange(params.receiver, params.old_parent);
    237   }
    238 }
    239 
    240 void FocusController::OnWindowHierarchyChanged(
    241     const HierarchyChangeParams& params) {
    242   if (params.receiver == focused_window_ &&
    243       params.target->Contains(params.receiver) && (!params.new_parent ||
    244       aura::client::GetFocusClient(params.new_parent) !=
    245           aura::client::GetFocusClient(params.receiver))) {
    246     WindowLostFocusFromDispositionChange(params.receiver, params.old_parent);
    247   }
    248 }
    249 
    250 ////////////////////////////////////////////////////////////////////////////////
    251 // FocusController, private:
    252 
    253 void FocusController::SetFocusedWindow(aura::Window* window) {
    254   if (updating_focus_ || window == focused_window_)
    255     return;
    256   DCHECK(rules_->CanFocusWindow(window));
    257   if (window)
    258     DCHECK_EQ(window, rules_->GetFocusableWindow(window));
    259 
    260   base::AutoReset<bool> updating_focus(&updating_focus_, true);
    261   aura::Window* lost_focus = focused_window_;
    262   if (focused_window_ && observer_manager_.IsObserving(focused_window_) &&
    263       focused_window_ != active_window_) {
    264     observer_manager_.Remove(focused_window_);
    265   }
    266   focused_window_ = window;
    267   if (focused_window_ && !observer_manager_.IsObserving(focused_window_))
    268     observer_manager_.Add(focused_window_);
    269 
    270   FOR_EACH_OBSERVER(aura::client::FocusChangeObserver,
    271                     focus_observers_,
    272                     OnWindowFocused(focused_window_, lost_focus));
    273   aura::client::FocusChangeObserver* observer =
    274       aura::client::GetFocusChangeObserver(lost_focus);
    275   if (observer)
    276     observer->OnWindowFocused(focused_window_, lost_focus);
    277   observer = aura::client::GetFocusChangeObserver(focused_window_);
    278   if (observer)
    279     observer->OnWindowFocused(focused_window_, lost_focus);
    280 }
    281 
    282 void FocusController::SetActiveWindow(aura::Window* requested_window,
    283                                       aura::Window* window) {
    284   if (updating_activation_)
    285     return;
    286 
    287   if (window == active_window_) {
    288     if (requested_window) {
    289       FOR_EACH_OBSERVER(aura::client::ActivationChangeObserver,
    290                         activation_observers_,
    291                         OnAttemptToReactivateWindow(requested_window,
    292                                                     active_window_));
    293     }
    294     return;
    295   }
    296 
    297   DCHECK(rules_->CanActivateWindow(window));
    298   if (window)
    299     DCHECK_EQ(window, rules_->GetActivatableWindow(window));
    300 
    301   base::AutoReset<bool> updating_activation(&updating_activation_, true);
    302   aura::Window* lost_activation = active_window_;
    303   if (active_window_ && observer_manager_.IsObserving(active_window_) &&
    304       focused_window_ != active_window_) {
    305     observer_manager_.Remove(active_window_);
    306   }
    307   active_window_ = window;
    308   if (active_window_ && !observer_manager_.IsObserving(active_window_))
    309     observer_manager_.Add(active_window_);
    310   if (active_window_) {
    311     StackTransientParentsBelowModalWindow(active_window_);
    312     active_window_->parent()->StackChildAtTop(active_window_);
    313   }
    314 
    315   aura::client::ActivationChangeObserver* observer =
    316       aura::client::GetActivationChangeObserver(lost_activation);
    317   if (observer)
    318     observer->OnWindowActivated(active_window_, lost_activation);
    319   observer = aura::client::GetActivationChangeObserver(active_window_);
    320   if (observer)
    321     observer->OnWindowActivated(active_window_, lost_activation);
    322   FOR_EACH_OBSERVER(aura::client::ActivationChangeObserver,
    323                     activation_observers_,
    324                     OnWindowActivated(active_window_, lost_activation));
    325 }
    326 
    327 void FocusController::WindowLostFocusFromDispositionChange(
    328     aura::Window* window,
    329     aura::Window* next) {
    330   // A window's modality state will interfere with focus restoration during its
    331   // destruction.
    332   window->ClearProperty(aura::client::kModalKey);
    333   // TODO(beng): See if this function can be replaced by a call to
    334   //             FocusWindow().
    335   // Activation adjustments are handled first in the event of a disposition
    336   // changed. If an activation change is necessary, focus is reset as part of
    337   // that process so there's no point in updating focus independently.
    338   if (window == active_window_) {
    339     aura::Window* next_activatable = rules_->GetNextActivatableWindow(window);
    340     SetActiveWindow(NULL, next_activatable);
    341     if (!(active_window_ && active_window_->Contains(focused_window_)))
    342       SetFocusedWindow(next_activatable);
    343   } else if (window->Contains(focused_window_)) {
    344     // Active window isn't changing, but focused window might be.
    345     SetFocusedWindow(rules_->GetFocusableWindow(next));
    346   }
    347 }
    348 
    349 void FocusController::WindowFocusedFromInputEvent(aura::Window* window) {
    350   // Only focus |window| if it or any of its parents can be focused. Otherwise
    351   // FocusWindow() will focus the topmost window, which may not be the
    352   // currently focused one.
    353   if (rules_->CanFocusWindow(GetToplevelWindow(window)))
    354     FocusWindow(window);
    355 }
    356 
    357 }  // namespace corewm
    358 }  // namespace views
    359