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