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) | |
sadrul
2012/12/04 16:19:40
The doc claims the window needs to be non-NULL. Bu
| |
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 |