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/corewm/window_modality_controller.h" | |
6 | |
7 #include <algorithm> | |
8 | |
9 #include "ui/aura/client/aura_constants.h" | |
10 #include "ui/aura/client/capture_client.h" | |
11 #include "ui/aura/env.h" | |
12 #include "ui/aura/window.h" | |
13 #include "ui/aura/window_event_dispatcher.h" | |
14 #include "ui/aura/window_property.h" | |
15 #include "ui/base/ui_base_types.h" | |
16 #include "ui/events/event.h" | |
17 #include "ui/events/event_target.h" | |
18 #include "ui/events/gestures/gesture_recognizer.h" | |
19 #include "ui/views/corewm/window_animations.h" | |
20 #include "ui/views/corewm/window_util.h" | |
21 | |
22 namespace views { | |
23 namespace corewm { | |
24 | |
25 // Transient child's modal parent. | |
26 extern const aura::WindowProperty<aura::Window*>* const kModalParentKey; | |
27 DEFINE_WINDOW_PROPERTY_KEY(aura::Window*, kModalParentKey, NULL); | |
28 | |
29 namespace { | |
30 | |
31 bool HasAncestor(aura::Window* window, aura::Window* ancestor) { | |
32 if (!window) | |
33 return false; | |
34 if (window == ancestor) | |
35 return true; | |
36 return HasAncestor(window->parent(), ancestor); | |
37 } | |
38 | |
39 bool TransientChildIsWindowModal(aura::Window* window) { | |
40 return window->GetProperty(aura::client::kModalKey) == ui::MODAL_TYPE_WINDOW; | |
41 } | |
42 | |
43 bool TransientChildIsSystemModal(aura::Window* window) { | |
44 return window->GetProperty(aura::client::kModalKey) == ui::MODAL_TYPE_SYSTEM; | |
45 } | |
46 | |
47 bool TransientChildIsChildModal(aura::Window* window) { | |
48 return window->GetProperty(aura::client::kModalKey) == ui::MODAL_TYPE_CHILD; | |
49 } | |
50 | |
51 aura::Window* GetModalParent(aura::Window* window) { | |
52 return window->GetProperty(kModalParentKey); | |
53 } | |
54 | |
55 bool IsModalTransientChild(aura::Window* transient, aura::Window* original) { | |
56 return transient->IsVisible() && | |
57 (TransientChildIsWindowModal(transient) || | |
58 TransientChildIsSystemModal(transient) || | |
59 (TransientChildIsChildModal(transient) && | |
60 (HasAncestor(original, GetModalParent(transient))))); | |
61 } | |
62 | |
63 aura::Window* GetModalTransientChild( | |
64 aura::Window* activatable, | |
65 aura::Window* original) { | |
66 for (aura::Window::Windows::const_iterator it = | |
67 GetTransientChildren(activatable).begin(); | |
68 it != GetTransientChildren(activatable).end(); | |
69 ++it) { | |
70 aura::Window* transient = *it; | |
71 if (IsModalTransientChild(transient, original)) { | |
72 return GetTransientChildren(transient).empty() ? | |
73 transient : GetModalTransientChild(transient, original); | |
74 } | |
75 } | |
76 return NULL; | |
77 } | |
78 | |
79 } // namespace | |
80 | |
81 void SetModalParent(aura::Window* child, aura::Window* parent) { | |
82 child->SetProperty(kModalParentKey, parent); | |
83 } | |
84 | |
85 aura::Window* GetModalTransient(aura::Window* window) { | |
86 if (!window) | |
87 return NULL; | |
88 | |
89 // We always want to check the for the transient child of the toplevel window. | |
90 aura::Window* toplevel = GetToplevelWindow(window); | |
91 if (!toplevel) | |
92 return NULL; | |
93 | |
94 return GetModalTransientChild(toplevel, window); | |
95 } | |
96 | |
97 //////////////////////////////////////////////////////////////////////////////// | |
98 // WindowModalityController, public: | |
99 | |
100 WindowModalityController::WindowModalityController( | |
101 ui::EventTarget* event_target) | |
102 : event_target_(event_target) { | |
103 aura::Env::GetInstance()->AddObserver(this); | |
104 DCHECK(event_target->IsPreTargetListEmpty()); | |
105 event_target_->AddPreTargetHandler(this); | |
106 } | |
107 | |
108 WindowModalityController::~WindowModalityController() { | |
109 event_target_->RemovePreTargetHandler(this); | |
110 aura::Env::GetInstance()->RemoveObserver(this); | |
111 for (size_t i = 0; i < windows_.size(); ++i) | |
112 windows_[i]->RemoveObserver(this); | |
113 } | |
114 | |
115 //////////////////////////////////////////////////////////////////////////////// | |
116 // WindowModalityController, aura::EventFilter implementation: | |
117 | |
118 void WindowModalityController::OnKeyEvent(ui::KeyEvent* event) { | |
119 aura::Window* target = static_cast<aura::Window*>(event->target()); | |
120 if (GetModalTransient(target)) | |
121 event->SetHandled(); | |
122 } | |
123 | |
124 void WindowModalityController::OnMouseEvent(ui::MouseEvent* event) { | |
125 aura::Window* target = static_cast<aura::Window*>(event->target()); | |
126 if (ProcessLocatedEvent(target, event)) | |
127 event->SetHandled(); | |
128 } | |
129 | |
130 void WindowModalityController::OnTouchEvent(ui::TouchEvent* event) { | |
131 aura::Window* target = static_cast<aura::Window*>(event->target()); | |
132 if (ProcessLocatedEvent(target, event)) | |
133 event->SetHandled(); | |
134 } | |
135 | |
136 //////////////////////////////////////////////////////////////////////////////// | |
137 // WindowModalityController, aura::EnvObserver implementation: | |
138 | |
139 void WindowModalityController::OnWindowInitialized(aura::Window* window) { | |
140 windows_.push_back(window); | |
141 window->AddObserver(this); | |
142 } | |
143 | |
144 //////////////////////////////////////////////////////////////////////////////// | |
145 // WindowModalityController, aura::WindowObserver implementation: | |
146 | |
147 void WindowModalityController::OnWindowPropertyChanged(aura::Window* window, | |
148 const void* key, | |
149 intptr_t old) { | |
150 // In tests, we sometimes create the modality relationship after a window is | |
151 // visible. | |
152 if (key == aura::client::kModalKey && | |
153 window->GetProperty(aura::client::kModalKey) != ui::MODAL_TYPE_NONE && | |
154 window->IsVisible()) { | |
155 ActivateWindow(window); | |
156 ui::GestureRecognizer::Get()->TransferEventsTo(GetTransientParent(window), | |
157 NULL); | |
158 } | |
159 } | |
160 | |
161 void WindowModalityController::OnWindowVisibilityChanged( | |
162 aura::Window* window, | |
163 bool visible) { | |
164 if (visible && window->GetProperty(aura::client::kModalKey) != | |
165 ui::MODAL_TYPE_NONE) { | |
166 ui::GestureRecognizer::Get()->TransferEventsTo(GetTransientParent(window), | |
167 NULL); | |
168 // Make sure no other window has capture, otherwise |window| won't get mouse | |
169 // events. | |
170 aura::Window* capture_window = aura::client::GetCaptureWindow(window); | |
171 if (capture_window) | |
172 capture_window->ReleaseCapture(); | |
173 } | |
174 } | |
175 | |
176 void WindowModalityController::OnWindowDestroyed(aura::Window* window) { | |
177 windows_.erase(std::find(windows_.begin(), windows_.end(), window)); | |
178 window->RemoveObserver(this); | |
179 } | |
180 | |
181 bool WindowModalityController::ProcessLocatedEvent(aura::Window* target, | |
182 ui::LocatedEvent* event) { | |
183 if (event->handled()) | |
184 return false; | |
185 aura::Window* modal_transient_child = GetModalTransient(target); | |
186 if (modal_transient_child && (event->type() == ui::ET_MOUSE_PRESSED || | |
187 event->type() == ui::ET_TOUCH_PRESSED)) { | |
188 AnimateWindow(modal_transient_child, WINDOW_ANIMATION_TYPE_BOUNCE); | |
189 } | |
190 if (event->type() == ui::ET_TOUCH_CANCELLED) | |
191 return false; | |
192 return !!modal_transient_child; | |
193 } | |
194 | |
195 } // namespace corewm | |
196 } // namespace views | |
OLD | NEW |