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 "ash/wm/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/root_window.h" | |
13 #include "ui/aura/window.h" | |
14 #include "ui/aura/window_property.h" | |
15 #include "ui/base/events/event.h" | |
16 #include "ui/base/ui_base_types.h" | |
17 #include "ui/views/corewm/window_animations.h" | |
18 #include "ui/views/corewm/window_util.h" | |
19 | |
20 namespace ash { | |
21 | |
22 // Transient child's modal parent. | |
23 extern const aura::WindowProperty<aura::Window*>* const kModalParentKey; | |
24 DEFINE_WINDOW_PROPERTY_KEY(aura::Window*, kModalParentKey, NULL); | |
25 | |
26 namespace { | |
27 | |
28 bool HasAncestor(aura::Window* window, aura::Window* ancestor) { | |
29 if (!window) | |
30 return false; | |
31 if (window == ancestor) | |
32 return true; | |
33 return HasAncestor(window->parent(), ancestor); | |
34 } | |
35 | |
36 bool TransientChildIsWindowModal(aura::Window* window) { | |
37 return window->GetProperty(aura::client::kModalKey) == ui::MODAL_TYPE_WINDOW; | |
38 } | |
39 | |
40 bool TransientChildIsChildModal(aura::Window* window) { | |
41 return window->GetProperty(aura::client::kModalKey) == ui::MODAL_TYPE_CHILD; | |
42 } | |
43 | |
44 aura::Window* GetModalParent(aura::Window* window) { | |
45 return window->GetProperty(kModalParentKey); | |
46 } | |
47 | |
48 bool IsModalTransientChild(aura::Window* transient, aura::Window* original) { | |
49 return transient->IsVisible() && | |
50 (TransientChildIsWindowModal(transient) || | |
51 (TransientChildIsChildModal(transient) && | |
52 (HasAncestor(original, GetModalParent(transient))))); | |
53 } | |
54 | |
55 aura::Window* GetModalTransientChild( | |
56 aura::Window* activatable, | |
57 aura::Window* original) { | |
58 aura::Window::Windows::const_iterator it; | |
59 for (it = activatable->transient_children().begin(); | |
60 it != activatable->transient_children().end(); | |
61 ++it) { | |
62 aura::Window* transient = *it; | |
63 if (IsModalTransientChild(transient, original)) { | |
64 return transient->transient_children().empty() ? | |
65 transient : GetModalTransientChild(transient, original); | |
66 } | |
67 } | |
68 return NULL; | |
69 } | |
70 | |
71 } // namespace | |
72 | |
73 void SetModalParent(aura::Window* child, aura::Window* parent) { | |
74 child->SetProperty(kModalParentKey, parent); | |
75 } | |
76 | |
77 aura::Window* GetModalTransient(aura::Window* window) { | |
78 if (!window) | |
79 return NULL; | |
80 | |
81 // We always want to check the for the transient child of the activatable | |
82 // window. | |
83 aura::Window* activatable = views::corewm::GetActivatableWindow(window); | |
84 if (!activatable) | |
85 return NULL; | |
86 | |
87 return GetModalTransientChild(activatable, window); | |
88 } | |
89 | |
90 namespace internal { | |
91 | |
92 //////////////////////////////////////////////////////////////////////////////// | |
93 // WindowModalityController, public: | |
94 | |
95 WindowModalityController::WindowModalityController() { | |
96 aura::Env::GetInstance()->AddObserver(this); | |
97 } | |
98 | |
99 WindowModalityController::~WindowModalityController() { | |
100 aura::Env::GetInstance()->RemoveObserver(this); | |
101 for (size_t i = 0; i < windows_.size(); ++i) | |
102 windows_[i]->RemoveObserver(this); | |
103 } | |
104 | |
105 //////////////////////////////////////////////////////////////////////////////// | |
106 // WindowModalityController, aura::EventFilter implementation: | |
107 | |
108 ui::EventResult WindowModalityController::OnKeyEvent(ui::KeyEvent* event) { | |
109 aura::Window* target = static_cast<aura::Window*>(event->target()); | |
110 return GetModalTransient(target) ? ui::ER_CONSUMED : ui::ER_UNHANDLED; | |
111 } | |
112 | |
113 ui::EventResult WindowModalityController::OnMouseEvent(ui::MouseEvent* event) { | |
114 aura::Window* target = static_cast<aura::Window*>(event->target()); | |
115 return ProcessLocatedEvent(target, event) ? ui::ER_CONSUMED : | |
116 ui::ER_UNHANDLED; | |
117 } | |
118 | |
119 ui::EventResult WindowModalityController::OnTouchEvent(ui::TouchEvent* event) { | |
120 aura::Window* target = static_cast<aura::Window*>(event->target()); | |
121 return ProcessLocatedEvent(target, event) ? ui::ER_CONSUMED : | |
122 ui::ER_UNHANDLED; | |
123 } | |
124 | |
125 void WindowModalityController::OnWindowInitialized(aura::Window* window) { | |
126 windows_.push_back(window); | |
127 window->AddObserver(this); | |
128 } | |
129 | |
130 void WindowModalityController::OnWindowVisibilityChanged( | |
131 aura::Window* window, | |
132 bool visible) { | |
133 if (visible && window->GetProperty(aura::client::kModalKey) == | |
134 ui::MODAL_TYPE_WINDOW) { | |
135 // Make sure no other window has capture, otherwise |window| won't get mouse | |
136 // events. | |
137 aura::Window* capture_window = aura::client::GetCaptureWindow(window); | |
138 if (capture_window) | |
139 capture_window->ReleaseCapture(); | |
140 } | |
141 } | |
142 | |
143 void WindowModalityController::OnWindowDestroyed(aura::Window* window) { | |
144 windows_.erase(std::find(windows_.begin(), windows_.end(), window)); | |
145 window->RemoveObserver(this); | |
146 } | |
147 | |
148 bool WindowModalityController::ProcessLocatedEvent(aura::Window* target, | |
149 ui::LocatedEvent* event) { | |
150 aura::Window* modal_transient_child = GetModalTransient(target); | |
151 if (modal_transient_child && (event->type() == ui::ET_MOUSE_PRESSED || | |
152 event->type() == ui::ET_TOUCH_PRESSED)) { | |
153 views::corewm::AnimateWindow(modal_transient_child, | |
154 views::corewm::WINDOW_ANIMATION_TYPE_BOUNCE); | |
155 } | |
156 return !!modal_transient_child; | |
157 } | |
158 | |
159 } // namespace internal | |
160 } // namespace ash | |
OLD | NEW |