OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/views/corewm/base_focus_rules.h" | 5 #include "ui/views/corewm/base_focus_rules.h" |
6 | 6 |
| 7 #include "ui/aura/client/activation_delegate.h" |
| 8 #include "ui/aura/client/focus_client.h" |
7 #include "ui/aura/root_window.h" | 9 #include "ui/aura/root_window.h" |
8 #include "ui/aura/window.h" | 10 #include "ui/aura/window.h" |
| 11 #include "ui/views/corewm/window_modality_controller.h" |
9 | 12 |
10 namespace views { | 13 namespace views { |
11 namespace corewm { | 14 namespace corewm { |
| 15 namespace { |
| 16 |
| 17 aura::Window* GetFocusedWindow(aura::Window* context) { |
| 18 aura::client::FocusClient* focus_client = |
| 19 aura::client::GetFocusClient(context); |
| 20 return focus_client ? focus_client->GetFocusedWindow() : NULL; |
| 21 } |
| 22 |
| 23 } // namespace |
12 | 24 |
13 //////////////////////////////////////////////////////////////////////////////// | 25 //////////////////////////////////////////////////////////////////////////////// |
14 // BaseFocusRules, public: | 26 // BaseFocusRules, protected: |
15 | 27 |
16 BaseFocusRules::BaseFocusRules() { | 28 BaseFocusRules::BaseFocusRules() { |
17 } | 29 } |
18 | 30 |
19 BaseFocusRules::~BaseFocusRules() { | 31 BaseFocusRules::~BaseFocusRules() { |
20 } | 32 } |
21 | 33 |
| 34 bool BaseFocusRules::IsWindowConsideredVisibleForActivation( |
| 35 aura::Window* window) { |
| 36 return window->IsVisible(); |
| 37 } |
| 38 |
22 //////////////////////////////////////////////////////////////////////////////// | 39 //////////////////////////////////////////////////////////////////////////////// |
23 // BaseFocusRules, FocusRules implementation: | 40 // BaseFocusRules, FocusRules implementation: |
24 | 41 |
25 bool BaseFocusRules::CanActivateWindow(aura::Window* window) { | 42 bool BaseFocusRules::CanActivateWindow(aura::Window* window) { |
26 return !window || | 43 // It is possible to activate a NULL window, it is equivalent to clearing |
27 (window->IsVisible() && window->parent() == window->GetRootWindow()); | 44 // activation. |
| 45 if (!window) |
| 46 return true; |
| 47 |
| 48 // The window must in a valid hierarchy. |
| 49 if (!window->GetRootWindow()) |
| 50 return false; |
| 51 |
| 52 // The window must be visible. |
| 53 if (!IsWindowConsideredVisibleForActivation(window)) |
| 54 return false; |
| 55 |
| 56 // The window's activation delegate must allow this window to be activated. |
| 57 if (aura::client::GetActivationDelegate(window) && |
| 58 !aura::client::GetActivationDelegate(window)->ShouldActivate()) { |
| 59 return false; |
| 60 } |
| 61 |
| 62 // The window must exist within a container that supports activation. |
| 63 // The window cannot be blocked by a modal transient. |
| 64 return SupportsChildActivation(window->parent()) && |
| 65 !GetModalTransientForActivatableWindow(window); |
28 } | 66 } |
29 | 67 |
30 bool BaseFocusRules::CanFocusWindow(aura::Window* window) { | 68 bool BaseFocusRules::CanFocusWindow(aura::Window* window) { |
31 // See FocusRules: NULL is a valid focusable window (when clearing focus). | 69 // It is possible to focus a NULL window, it is equivalent to clearing focus. |
32 return !window || window->CanFocus(); | 70 if (!window) |
| 71 return true; |
| 72 |
| 73 // The focused window is always inside the active window, so windows that |
| 74 // aren't activatable can't contain the focused window. |
| 75 aura::Window* activatable = GetActivatableWindow(window); |
| 76 if (!activatable->Contains(window)) |
| 77 return false; |
| 78 return window->CanFocus(); |
33 } | 79 } |
34 | 80 |
35 aura::Window* BaseFocusRules::GetActivatableWindow(aura::Window* window) { | 81 aura::Window* BaseFocusRules::GetActivatableWindow(aura::Window* window) { |
36 // BasicFocusRules considers only direct children of the RootWindow as | |
37 // activatable. | |
38 aura::Window* parent = window->parent(); | 82 aura::Window* parent = window->parent(); |
39 aura::Window* activatable = window; | 83 aura::Window* child = window; |
40 aura::RootWindow* root_window = window->GetRootWindow(); | 84 while (parent) { |
41 while (parent != root_window) { | 85 if (CanActivateWindow(child)) |
42 activatable = parent; | 86 return child; |
| 87 |
| 88 if (child->transient_parent()) |
| 89 return GetActivatableWindow(child->transient_parent()); |
| 90 |
43 parent = parent->parent(); | 91 parent = parent->parent(); |
| 92 child = child->parent(); |
44 } | 93 } |
45 return activatable; | 94 return NULL; |
46 } | 95 } |
47 | 96 |
48 aura::Window* BaseFocusRules::GetFocusableWindow(aura::Window* window) { | 97 aura::Window* BaseFocusRules::GetFocusableWindow(aura::Window* window) { |
| 98 if (CanFocusWindow(window)) |
| 99 return window; |
| 100 |
| 101 // |window| may be in a hierarchy that is non-activatable, in which case we |
| 102 // need to cut over to the activatable hierarchy. |
| 103 aura::Window* activatable = GetActivatableWindow(window); |
| 104 if (!activatable) |
| 105 return GetFocusedWindow(window); |
| 106 |
| 107 if (!activatable->Contains(window)) { |
| 108 // If there's already a child window focused in the activatable hierarchy, |
| 109 // just use that (i.e. don't shift focus), otherwise we need to at least cut |
| 110 // over to the activatable hierarchy. |
| 111 aura::Window* focused = GetFocusedWindow(activatable); |
| 112 return activatable->Contains(focused) ? focused : activatable; |
| 113 } |
| 114 |
49 while (window && !CanFocusWindow(window)) | 115 while (window && !CanFocusWindow(window)) |
50 window = window->parent(); | 116 window = window->parent(); |
51 return window; | 117 return window; |
52 } | 118 } |
53 | 119 |
54 aura::Window* BaseFocusRules::GetNextActivatableWindow(aura::Window* ignore) { | 120 aura::Window* BaseFocusRules::GetNextActivatableWindow(aura::Window* ignore) { |
55 DCHECK(ignore); | 121 DCHECK(ignore); |
56 | 122 |
57 // Can be called from the RootWindow's destruction, which has a NULL parent. | 123 // Can be called from the RootWindow's destruction, which has a NULL parent. |
58 if (!ignore->parent()) | 124 if (!ignore->parent()) |
(...skipping 22 matching lines...) Expand all Loading... |
81 // Focus cycling is currently very primitive: we just climb the tree. | 147 // Focus cycling is currently very primitive: we just climb the tree. |
82 // If need be, we could add the ability to look at siblings, descend etc. | 148 // If need be, we could add the ability to look at siblings, descend etc. |
83 // For test coverage, see FocusControllerImplicitTestBase subclasses in | 149 // For test coverage, see FocusControllerImplicitTestBase subclasses in |
84 // focus_controller_unittest.cc. | 150 // focus_controller_unittest.cc. |
85 return GetFocusableWindow(ignore->parent()); | 151 return GetFocusableWindow(ignore->parent()); |
86 } | 152 } |
87 | 153 |
88 | 154 |
89 } // namespace corewm | 155 } // namespace corewm |
90 } // namespace views | 156 } // namespace views |
OLD | NEW |