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