OLD | NEW |
| (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/widget/desktop_aura/desktop_activation_client.h" | |
6 | |
7 #include "base/auto_reset.h" | |
8 #include "base/compiler_specific.h" | |
9 #include "ui/aura/client/activation_delegate.h" | |
10 #include "ui/aura/client/activation_change_observer.h" | |
11 #include "ui/aura/client/focus_client.h" | |
12 #include "ui/aura/root_window.h" | |
13 #include "ui/aura/window.h" | |
14 | |
15 namespace views { | |
16 | |
17 namespace { | |
18 | |
19 aura::Window* FindFocusableWindowFor(aura::Window* window) { | |
20 while (window && !window->CanFocus()) | |
21 window = window->parent(); | |
22 return window; | |
23 } | |
24 | |
25 } // namespace | |
26 | |
27 DesktopActivationClient::DesktopActivationClient(aura::RootWindow* root_window) | |
28 : root_window_(root_window), | |
29 current_active_(NULL), | |
30 updating_activation_(false), | |
31 observer_manager_(this) { | |
32 aura::client::GetFocusClient(root_window_)->AddObserver(this); | |
33 aura::client::SetActivationClient(root_window_, this); | |
34 root_window->AddPreTargetHandler(this); | |
35 } | |
36 | |
37 DesktopActivationClient::~DesktopActivationClient() { | |
38 root_window_->RemovePreTargetHandler(this); | |
39 aura::client::GetFocusClient(root_window_)->RemoveObserver(this); | |
40 aura::client::SetActivationClient(root_window_, NULL); | |
41 } | |
42 | |
43 void DesktopActivationClient::AddObserver( | |
44 aura::client::ActivationChangeObserver* observer) { | |
45 observers_.AddObserver(observer); | |
46 } | |
47 | |
48 void DesktopActivationClient::RemoveObserver( | |
49 aura::client::ActivationChangeObserver* observer) { | |
50 observers_.RemoveObserver(observer); | |
51 } | |
52 | |
53 void DesktopActivationClient::ActivateWindow(aura::Window* window) { | |
54 // Prevent recursion when called from focus. | |
55 if (updating_activation_) | |
56 return; | |
57 | |
58 base::AutoReset<bool> in_activate_window(&updating_activation_, true); | |
59 // Nothing may actually have changed. | |
60 if (current_active_ == window) | |
61 return; | |
62 // The stacking client may impose rules on what window configurations can be | |
63 // activated or deactivated. | |
64 if (window && !CanActivateWindow(window)) | |
65 return; | |
66 // Switch internal focus before we change the activation. Will probably cause | |
67 // recursion. | |
68 if (window && | |
69 !window->Contains(aura::client::GetFocusClient(window)-> | |
70 GetFocusedWindow())) { | |
71 aura::client::GetFocusClient(window)->FocusWindow(window); | |
72 } | |
73 | |
74 aura::Window* old_active = current_active_; | |
75 current_active_ = window; | |
76 if (window && !observer_manager_.IsObserving(window)) | |
77 observer_manager_.Add(window); | |
78 | |
79 FOR_EACH_OBSERVER(aura::client::ActivationChangeObserver, | |
80 observers_, | |
81 OnWindowActivated(window, old_active)); | |
82 aura::client::ActivationChangeObserver* observer = | |
83 aura::client::GetActivationChangeObserver(old_active); | |
84 if (observer) | |
85 observer->OnWindowActivated(window, old_active); | |
86 observer = aura::client::GetActivationChangeObserver(window); | |
87 if (observer) | |
88 observer->OnWindowActivated(window, old_active); | |
89 } | |
90 | |
91 void DesktopActivationClient::DeactivateWindow(aura::Window* window) { | |
92 if (window == current_active_) | |
93 current_active_ = NULL; | |
94 } | |
95 | |
96 aura::Window* DesktopActivationClient::GetActiveWindow() { | |
97 return current_active_; | |
98 } | |
99 | |
100 aura::Window* DesktopActivationClient::GetActivatableWindow( | |
101 aura::Window* window) { | |
102 aura::Window* parent = window->parent(); | |
103 aura::Window* child = window; | |
104 while (parent) { | |
105 if (CanActivateWindow(child)) | |
106 return child; | |
107 // If |child| isn't activatable, but has transient parent, trace | |
108 // that path instead. | |
109 if (child->transient_parent()) | |
110 return GetActivatableWindow(child->transient_parent()); | |
111 parent = parent->parent(); | |
112 child = child->parent(); | |
113 } | |
114 return NULL; | |
115 } | |
116 | |
117 aura::Window* DesktopActivationClient::GetToplevelWindow(aura::Window* window) { | |
118 aura::Window* parent = window->parent(); | |
119 aura::Window* child = window; | |
120 aura::Window* root = child->GetRootWindow(); | |
121 while (parent) { | |
122 if (parent == root) | |
123 return child; | |
124 parent = parent->parent(); | |
125 child = child->parent(); | |
126 } | |
127 return NULL; | |
128 } | |
129 | |
130 bool DesktopActivationClient::OnWillFocusWindow(aura::Window* window, | |
131 const ui::Event* event) { | |
132 return CanActivateWindow(GetActivatableWindow(window)); | |
133 } | |
134 | |
135 void DesktopActivationClient::OnWindowDestroying(aura::Window* window) { | |
136 if (current_active_ == window) { | |
137 current_active_ = NULL; | |
138 FOR_EACH_OBSERVER(aura::client::ActivationChangeObserver, | |
139 observers_, | |
140 OnWindowActivated(NULL, window)); | |
141 | |
142 // ash::ActivationController will also activate the next window here; we | |
143 // don't do this because that's the desktop environment's job. | |
144 } | |
145 observer_manager_.Remove(window); | |
146 } | |
147 | |
148 void DesktopActivationClient::OnWindowFocused(aura::Window* gained_focus, | |
149 aura::Window* lost_focus) { | |
150 if (gained_focus) | |
151 ActivateWindow(GetActivatableWindow(gained_focus)); | |
152 } | |
153 | |
154 bool DesktopActivationClient::CanActivateWindow(aura::Window* window) const { | |
155 return window && | |
156 window->IsVisible() && | |
157 (!aura::client::GetActivationDelegate(window) || | |
158 aura::client::GetActivationDelegate(window)->ShouldActivate()); | |
159 } | |
160 | |
161 void DesktopActivationClient::OnKeyEvent(ui::KeyEvent* event) { | |
162 } | |
163 | |
164 void DesktopActivationClient::OnMouseEvent(ui::MouseEvent* event) { | |
165 if (event->type() == ui::ET_MOUSE_PRESSED) | |
166 FocusWindowWithEvent(event); | |
167 } | |
168 | |
169 void DesktopActivationClient::OnScrollEvent(ui::ScrollEvent* event) { | |
170 } | |
171 | |
172 void DesktopActivationClient::OnTouchEvent(ui::TouchEvent* event) { | |
173 } | |
174 | |
175 void DesktopActivationClient::OnGestureEvent(ui::GestureEvent* event) { | |
176 if (event->type() == ui::ET_GESTURE_BEGIN && | |
177 event->details().touch_points() == 1) { | |
178 FocusWindowWithEvent(event); | |
179 } | |
180 } | |
181 | |
182 void DesktopActivationClient::FocusWindowWithEvent(const ui::Event* event) { | |
183 aura::Window* window = static_cast<aura::Window*>(event->target()); | |
184 if (GetActiveWindow() != window) { | |
185 aura::client::GetFocusClient(window)->FocusWindow( | |
186 FindFocusableWindowFor(window)); | |
187 } | |
188 } | |
189 | |
190 } // namespace views | |
OLD | NEW |