Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(143)

Side by Side Diff: ui/views/corewm/base_focus_rules.cc

Issue 194843004: Move files from ui/views/corewm to ui/wm/core (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ui/views/corewm/base_focus_rules.h ('k') | ui/views/corewm/capture_controller.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 "ui/views/corewm/base_focus_rules.h"
6
7 #include "ui/aura/client/activation_delegate.h"
8 #include "ui/aura/client/focus_client.h"
9 #include "ui/aura/window.h"
10 #include "ui/aura/window_event_dispatcher.h"
11 #include "ui/views/corewm/window_modality_controller.h"
12 #include "ui/views/corewm/window_util.h"
13
14 namespace views {
15 namespace corewm {
16 namespace {
17
18 aura::Window* GetFocusedWindow(aura::Window* context) {
19 aura::client::FocusClient* focus_client =
20 aura::client::GetFocusClient(context);
21 return focus_client ? focus_client->GetFocusedWindow() : NULL;
22 }
23
24 } // namespace
25
26 ////////////////////////////////////////////////////////////////////////////////
27 // BaseFocusRules, protected:
28
29 BaseFocusRules::BaseFocusRules() {
30 }
31
32 BaseFocusRules::~BaseFocusRules() {
33 }
34
35 bool BaseFocusRules::IsWindowConsideredVisibleForActivation(
36 aura::Window* window) const {
37 return window->IsVisible();
38 }
39
40 ////////////////////////////////////////////////////////////////////////////////
41 // BaseFocusRules, FocusRules implementation:
42
43 bool BaseFocusRules::IsToplevelWindow(aura::Window* window) const {
44 // The window must in a valid hierarchy.
45 if (!window->GetRootWindow())
46 return false;
47
48 // The window must exist within a container that supports activation.
49 // The window cannot be blocked by a modal transient.
50 return SupportsChildActivation(window->parent());
51 }
52
53 bool BaseFocusRules::CanActivateWindow(aura::Window* window) const {
54 // It is possible to activate a NULL window, it is equivalent to clearing
55 // activation.
56 if (!window)
57 return true;
58
59 // Only toplevel windows can be activated.
60 if (!IsToplevelWindow(window))
61 return false;
62
63 // The window must be visible.
64 if (!IsWindowConsideredVisibleForActivation(window))
65 return false;
66
67 // The window's activation delegate must allow this window to be activated.
68 if (aura::client::GetActivationDelegate(window) &&
69 !aura::client::GetActivationDelegate(window)->ShouldActivate()) {
70 return false;
71 }
72
73 // A window must be focusable to be activatable. We don't call
74 // CanFocusWindow() from here because it will call back to us via
75 // GetActivatableWindow().
76 if (!window->CanFocus())
77 return false;
78
79 // The window cannot be blocked by a modal transient.
80 return !GetModalTransient(window);
81 }
82
83 bool BaseFocusRules::CanFocusWindow(aura::Window* window) const {
84 // It is possible to focus a NULL window, it is equivalent to clearing focus.
85 if (!window)
86 return true;
87
88 // The focused window is always inside the active window, so windows that
89 // aren't activatable can't contain the focused window.
90 aura::Window* activatable = GetActivatableWindow(window);
91 if (!activatable || !activatable->Contains(window))
92 return false;
93 return window->CanFocus();
94 }
95
96 aura::Window* BaseFocusRules::GetToplevelWindow(aura::Window* window) const {
97 aura::Window* parent = window->parent();
98 aura::Window* child = window;
99 while (parent) {
100 if (IsToplevelWindow(child))
101 return child;
102
103 parent = parent->parent();
104 child = child->parent();
105 }
106 return NULL;
107 }
108
109 aura::Window* BaseFocusRules::GetActivatableWindow(aura::Window* window) const {
110 aura::Window* parent = window->parent();
111 aura::Window* child = window;
112 while (parent) {
113 if (CanActivateWindow(child))
114 return child;
115
116 // CanActivateWindow() above will return false if |child| is blocked by a
117 // modal transient. In this case the modal is or contains the activatable
118 // window. We recurse because the modal may itself be blocked by a modal
119 // transient.
120 aura::Window* modal_transient = GetModalTransient(child);
121 if (modal_transient)
122 return GetActivatableWindow(modal_transient);
123
124 if (views::corewm::GetTransientParent(child)) {
125 // To avoid infinite recursion, if |child| has a transient parent
126 // whose own modal transient is |child| itself, just return |child|.
127 aura::Window* parent_modal_transient =
128 GetModalTransient(views::corewm::GetTransientParent(child));
129 if (parent_modal_transient == child)
130 return child;
131
132 return GetActivatableWindow(views::corewm::GetTransientParent(child));
133 }
134
135 parent = parent->parent();
136 child = child->parent();
137 }
138 return NULL;
139 }
140
141 aura::Window* BaseFocusRules::GetFocusableWindow(aura::Window* window) const {
142 if (CanFocusWindow(window))
143 return window;
144
145 // |window| may be in a hierarchy that is non-activatable, in which case we
146 // need to cut over to the activatable hierarchy.
147 aura::Window* activatable = GetActivatableWindow(window);
148 if (!activatable) {
149 // There may not be a related activatable hierarchy to cut over to, in which
150 // case we try an unrelated one.
151 aura::Window* toplevel = GetToplevelWindow(window);
152 if (toplevel)
153 activatable = GetNextActivatableWindow(toplevel);
154 if (!activatable)
155 return NULL;
156 }
157
158 if (!activatable->Contains(window)) {
159 // If there's already a child window focused in the activatable hierarchy,
160 // just use that (i.e. don't shift focus), otherwise we need to at least cut
161 // over to the activatable hierarchy.
162 aura::Window* focused = GetFocusedWindow(activatable);
163 return activatable->Contains(focused) ? focused : activatable;
164 }
165
166 while (window && !CanFocusWindow(window))
167 window = window->parent();
168 return window;
169 }
170
171 aura::Window* BaseFocusRules::GetNextActivatableWindow(
172 aura::Window* ignore) const {
173 DCHECK(ignore);
174
175 // Can be called from the RootWindow's destruction, which has a NULL parent.
176 if (!ignore->parent())
177 return NULL;
178
179 // In the basic scenarios handled by BasicFocusRules, the pool of activatable
180 // windows is limited to the |ignore|'s siblings.
181 const aura::Window::Windows& siblings = ignore->parent()->children();
182 DCHECK(!siblings.empty());
183
184 for (aura::Window::Windows::const_reverse_iterator rit = siblings.rbegin();
185 rit != siblings.rend();
186 ++rit) {
187 aura::Window* cur = *rit;
188 if (cur == ignore)
189 continue;
190 if (CanActivateWindow(cur))
191 return cur;
192 }
193 return NULL;
194 }
195
196 } // namespace corewm
197 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/corewm/base_focus_rules.h ('k') | ui/views/corewm/capture_controller.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698