| OLD | NEW |
| (Empty) |
| 1 // Copyright 2015 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 "components/mus/ws/event_dispatcher.h" | |
| 6 | |
| 7 #include <algorithm> | |
| 8 | |
| 9 #include "base/time/time.h" | |
| 10 #include "components/mus/ws/accelerator.h" | |
| 11 #include "components/mus/ws/display.h" | |
| 12 #include "components/mus/ws/event_dispatcher_delegate.h" | |
| 13 #include "components/mus/ws/server_window.h" | |
| 14 #include "components/mus/ws/server_window_delegate.h" | |
| 15 #include "components/mus/ws/window_coordinate_conversions.h" | |
| 16 #include "components/mus/ws/window_finder.h" | |
| 17 #include "ui/events/event_utils.h" | |
| 18 #include "ui/gfx/geometry/point.h" | |
| 19 #include "ui/gfx/geometry/point_conversions.h" | |
| 20 | |
| 21 namespace mus { | |
| 22 namespace ws { | |
| 23 | |
| 24 using Entry = std::pair<uint32_t, std::unique_ptr<Accelerator>>; | |
| 25 | |
| 26 namespace { | |
| 27 | |
| 28 bool IsOnlyOneMouseButtonDown(int flags) { | |
| 29 const uint32_t button_only_flags = | |
| 30 flags & (ui::EF_LEFT_MOUSE_BUTTON | ui::EF_MIDDLE_MOUSE_BUTTON | | |
| 31 ui::EF_RIGHT_MOUSE_BUTTON); | |
| 32 return button_only_flags == ui::EF_LEFT_MOUSE_BUTTON || | |
| 33 button_only_flags == ui::EF_MIDDLE_MOUSE_BUTTON || | |
| 34 button_only_flags == ui::EF_RIGHT_MOUSE_BUTTON; | |
| 35 } | |
| 36 | |
| 37 bool IsLocationInNonclientArea(const ServerWindow* target, | |
| 38 const gfx::Point& location) { | |
| 39 if (!target->parent()) | |
| 40 return false; | |
| 41 | |
| 42 gfx::Rect client_area(target->bounds().size()); | |
| 43 client_area.Inset(target->client_area()); | |
| 44 if (client_area.Contains(location)) | |
| 45 return false; | |
| 46 | |
| 47 for (const auto& rect : target->additional_client_areas()) { | |
| 48 if (rect.Contains(location)) | |
| 49 return false; | |
| 50 } | |
| 51 | |
| 52 return true; | |
| 53 } | |
| 54 | |
| 55 uint32_t PointerId(const ui::LocatedEvent& event) { | |
| 56 if (event.IsPointerEvent()) | |
| 57 return event.AsPointerEvent()->pointer_id(); | |
| 58 if (event.IsMouseWheelEvent()) | |
| 59 return ui::PointerEvent::kMousePointerId; | |
| 60 | |
| 61 NOTREACHED(); | |
| 62 return 0; | |
| 63 } | |
| 64 | |
| 65 } // namespace | |
| 66 | |
| 67 //////////////////////////////////////////////////////////////////////////////// | |
| 68 | |
| 69 EventDispatcher::EventDispatcher(EventDispatcherDelegate* delegate) | |
| 70 : delegate_(delegate), | |
| 71 capture_window_(nullptr), | |
| 72 capture_window_client_id_(kInvalidClientId), | |
| 73 modal_window_controller_(this), | |
| 74 mouse_button_down_(false), | |
| 75 mouse_cursor_source_window_(nullptr), | |
| 76 mouse_cursor_in_non_client_area_(false) {} | |
| 77 | |
| 78 EventDispatcher::~EventDispatcher() { | |
| 79 if (capture_window_) { | |
| 80 UnobserveWindow(capture_window_); | |
| 81 capture_window_ = nullptr; | |
| 82 capture_window_client_id_ = kInvalidClientId; | |
| 83 } | |
| 84 for (const auto& pair : pointer_targets_) { | |
| 85 if (pair.second.window) | |
| 86 UnobserveWindow(pair.second.window); | |
| 87 } | |
| 88 pointer_targets_.clear(); | |
| 89 } | |
| 90 | |
| 91 void EventDispatcher::Reset() { | |
| 92 if (capture_window_) { | |
| 93 CancelPointerEventsToTarget(capture_window_); | |
| 94 DCHECK(capture_window_ == nullptr); | |
| 95 } | |
| 96 | |
| 97 while (!pointer_targets_.empty()) | |
| 98 StopTrackingPointer(pointer_targets_.begin()->first); | |
| 99 | |
| 100 mouse_button_down_ = false; | |
| 101 } | |
| 102 | |
| 103 void EventDispatcher::SetMousePointerScreenLocation( | |
| 104 const gfx::Point& screen_location) { | |
| 105 DCHECK(pointer_targets_.empty()); | |
| 106 mouse_pointer_last_location_ = screen_location; | |
| 107 UpdateCursorProviderByLastKnownLocation(); | |
| 108 // Write our initial location back to our shared screen coordinate. This | |
| 109 // shouldn't cause problems because we already read the cursor before we | |
| 110 // process any events in views during window construction. | |
| 111 delegate_->OnMouseCursorLocationChanged(screen_location); | |
| 112 } | |
| 113 | |
| 114 bool EventDispatcher::GetCurrentMouseCursor(int32_t* cursor_out) { | |
| 115 if (!mouse_cursor_source_window_) | |
| 116 return false; | |
| 117 | |
| 118 *cursor_out = mouse_cursor_in_non_client_area_ | |
| 119 ? mouse_cursor_source_window_->non_client_cursor() | |
| 120 : mouse_cursor_source_window_->cursor(); | |
| 121 return true; | |
| 122 } | |
| 123 | |
| 124 bool EventDispatcher::SetCaptureWindow(ServerWindow* window, | |
| 125 ClientSpecificId client_id) { | |
| 126 if (!window) | |
| 127 client_id = kInvalidClientId; | |
| 128 | |
| 129 if (window == capture_window_ && client_id == capture_window_client_id_) | |
| 130 return true; | |
| 131 | |
| 132 // A window that is blocked by a modal window cannot gain capture. | |
| 133 if (window && modal_window_controller_.IsWindowBlocked(window)) | |
| 134 return false; | |
| 135 | |
| 136 if (capture_window_) { | |
| 137 // Stop observing old capture window. |pointer_targets_| are cleared on | |
| 138 // initial setting of a capture window. | |
| 139 delegate_->OnServerWindowCaptureLost(capture_window_); | |
| 140 UnobserveWindow(capture_window_); | |
| 141 } else { | |
| 142 // Cancel implicit capture to all other windows. | |
| 143 for (const auto& pair : pointer_targets_) { | |
| 144 ServerWindow* target = pair.second.window; | |
| 145 if (!target) | |
| 146 continue; | |
| 147 UnobserveWindow(target); | |
| 148 if (target == window) | |
| 149 continue; | |
| 150 | |
| 151 ui::EventType event_type = pair.second.is_mouse_event | |
| 152 ? ui::ET_POINTER_EXITED | |
| 153 : ui::ET_POINTER_CANCELLED; | |
| 154 ui::EventPointerType pointer_type = | |
| 155 pair.second.is_mouse_event ? ui::EventPointerType::POINTER_TYPE_MOUSE | |
| 156 : ui::EventPointerType::POINTER_TYPE_TOUCH; | |
| 157 // TODO(jonross): Track previous location in PointerTarget for sending | |
| 158 // cancels. | |
| 159 ui::PointerEvent event( | |
| 160 event_type, gfx::Point(), gfx::Point(), ui::EF_NONE, pair.first, | |
| 161 ui::PointerDetails(pointer_type), ui::EventTimeForNow()); | |
| 162 DispatchToPointerTarget(pair.second, event); | |
| 163 } | |
| 164 pointer_targets_.clear(); | |
| 165 } | |
| 166 | |
| 167 // Set the capture before changing native capture; otherwise, the callback | |
| 168 // from native platform might try to set the capture again. | |
| 169 bool had_capture_window = capture_window_ != nullptr; | |
| 170 capture_window_ = window; | |
| 171 capture_window_client_id_ = client_id; | |
| 172 | |
| 173 // Begin tracking the capture window if it is not yet being observed. | |
| 174 if (window) { | |
| 175 ObserveWindow(window); | |
| 176 // TODO(sky): this conditional is problematic for the case of capture moving | |
| 177 // to a different display. | |
| 178 if (!had_capture_window) | |
| 179 delegate_->SetNativeCapture(window); | |
| 180 } else { | |
| 181 delegate_->ReleaseNativeCapture(); | |
| 182 if (!mouse_button_down_) | |
| 183 UpdateCursorProviderByLastKnownLocation(); | |
| 184 } | |
| 185 | |
| 186 return true; | |
| 187 } | |
| 188 | |
| 189 void EventDispatcher::AddSystemModalWindow(ServerWindow* window) { | |
| 190 modal_window_controller_.AddSystemModalWindow(window); | |
| 191 } | |
| 192 | |
| 193 void EventDispatcher::ReleaseCaptureBlockedByModalWindow( | |
| 194 const ServerWindow* modal_window) { | |
| 195 if (!capture_window_) | |
| 196 return; | |
| 197 | |
| 198 if (modal_window_controller_.IsWindowBlockedBy(capture_window_, | |
| 199 modal_window)) { | |
| 200 SetCaptureWindow(nullptr, kInvalidClientId); | |
| 201 } | |
| 202 } | |
| 203 | |
| 204 void EventDispatcher::ReleaseCaptureBlockedByAnyModalWindow() { | |
| 205 if (!capture_window_) | |
| 206 return; | |
| 207 | |
| 208 if (modal_window_controller_.IsWindowBlocked(capture_window_)) | |
| 209 SetCaptureWindow(nullptr, kInvalidClientId); | |
| 210 } | |
| 211 | |
| 212 void EventDispatcher::UpdateNonClientAreaForCurrentWindow() { | |
| 213 if (mouse_cursor_source_window_) { | |
| 214 gfx::Point location = mouse_pointer_last_location_; | |
| 215 ServerWindow* target = FindDeepestVisibleWindowForEvents(&location); | |
| 216 if (target == mouse_cursor_source_window_) { | |
| 217 mouse_cursor_in_non_client_area_ = | |
| 218 mouse_cursor_source_window_ | |
| 219 ? IsLocationInNonclientArea(mouse_cursor_source_window_, location) | |
| 220 : false; | |
| 221 } | |
| 222 } | |
| 223 } | |
| 224 | |
| 225 void EventDispatcher::UpdateCursorProviderByLastKnownLocation() { | |
| 226 if (!mouse_button_down_) { | |
| 227 gfx::Point location = mouse_pointer_last_location_; | |
| 228 mouse_cursor_source_window_ = FindDeepestVisibleWindowForEvents(&location); | |
| 229 | |
| 230 mouse_cursor_in_non_client_area_ = | |
| 231 mouse_cursor_source_window_ | |
| 232 ? IsLocationInNonclientArea(mouse_cursor_source_window_, location) | |
| 233 : false; | |
| 234 } | |
| 235 } | |
| 236 | |
| 237 bool EventDispatcher::AddAccelerator(uint32_t id, | |
| 238 mojom::EventMatcherPtr event_matcher) { | |
| 239 std::unique_ptr<Accelerator> accelerator(new Accelerator(id, *event_matcher)); | |
| 240 // If an accelerator with the same id or matcher already exists, then abort. | |
| 241 for (const auto& pair : accelerators_) { | |
| 242 if (pair.first == id || accelerator->EqualEventMatcher(pair.second.get())) | |
| 243 return false; | |
| 244 } | |
| 245 accelerators_.insert(Entry(id, std::move(accelerator))); | |
| 246 return true; | |
| 247 } | |
| 248 | |
| 249 void EventDispatcher::RemoveAccelerator(uint32_t id) { | |
| 250 auto it = accelerators_.find(id); | |
| 251 // Clients may pass bogus ids. | |
| 252 if (it != accelerators_.end()) | |
| 253 accelerators_.erase(it); | |
| 254 } | |
| 255 | |
| 256 void EventDispatcher::ProcessEvent(const ui::Event& event) { | |
| 257 if (event.IsKeyEvent()) { | |
| 258 const ui::KeyEvent* key_event = event.AsKeyEvent(); | |
| 259 if (event.type() == ui::ET_KEY_PRESSED && !key_event->is_char()) { | |
| 260 Accelerator* pre_target = | |
| 261 FindAccelerator(*key_event, ui::mojom::AcceleratorPhase::PRE_TARGET); | |
| 262 if (pre_target) { | |
| 263 delegate_->OnAccelerator(pre_target->id(), event); | |
| 264 return; | |
| 265 } | |
| 266 } | |
| 267 ProcessKeyEvent(*key_event); | |
| 268 return; | |
| 269 } | |
| 270 | |
| 271 if (event.IsPointerEvent() || event.IsMouseWheelEvent()) { | |
| 272 ProcessLocatedEvent(*event.AsLocatedEvent()); | |
| 273 return; | |
| 274 } | |
| 275 | |
| 276 NOTREACHED(); | |
| 277 } | |
| 278 | |
| 279 void EventDispatcher::ProcessKeyEvent(const ui::KeyEvent& event) { | |
| 280 Accelerator* post_target = | |
| 281 FindAccelerator(event, ui::mojom::AcceleratorPhase::POST_TARGET); | |
| 282 ServerWindow* focused_window = | |
| 283 delegate_->GetFocusedWindowForEventDispatcher(); | |
| 284 if (focused_window) { | |
| 285 // Assume key events are for the client area. | |
| 286 const bool in_nonclient_area = false; | |
| 287 const ClientSpecificId client_id = | |
| 288 delegate_->GetEventTargetClientId(focused_window, in_nonclient_area); | |
| 289 delegate_->DispatchInputEventToWindow(focused_window, client_id, event, | |
| 290 post_target); | |
| 291 return; | |
| 292 } | |
| 293 delegate_->OnEventTargetNotFound(event); | |
| 294 if (post_target) | |
| 295 delegate_->OnAccelerator(post_target->id(), event); | |
| 296 } | |
| 297 | |
| 298 void EventDispatcher::ProcessLocatedEvent(const ui::LocatedEvent& event) { | |
| 299 DCHECK(event.IsPointerEvent() || event.IsMouseWheelEvent()); | |
| 300 const bool is_mouse_event = | |
| 301 event.IsMousePointerEvent() || event.IsMouseWheelEvent(); | |
| 302 | |
| 303 if (is_mouse_event) { | |
| 304 mouse_pointer_last_location_ = event.location(); | |
| 305 delegate_->OnMouseCursorLocationChanged(event.root_location()); | |
| 306 } | |
| 307 | |
| 308 // Release capture on pointer up. For mouse we only release if there are | |
| 309 // no buttons down. | |
| 310 const bool is_pointer_going_up = | |
| 311 (event.type() == ui::ET_POINTER_UP || | |
| 312 event.type() == ui::ET_POINTER_CANCELLED) && | |
| 313 (!is_mouse_event || IsOnlyOneMouseButtonDown(event.flags())); | |
| 314 | |
| 315 // Update mouse down state upon events which change it. | |
| 316 if (is_mouse_event) { | |
| 317 if (event.type() == ui::ET_POINTER_DOWN) | |
| 318 mouse_button_down_ = true; | |
| 319 else if (is_pointer_going_up) | |
| 320 mouse_button_down_ = false; | |
| 321 } | |
| 322 | |
| 323 if (capture_window_) { | |
| 324 mouse_cursor_source_window_ = capture_window_; | |
| 325 DispatchToClient(capture_window_, capture_window_client_id_, event); | |
| 326 return; | |
| 327 } | |
| 328 | |
| 329 const int32_t pointer_id = PointerId(event); | |
| 330 if (!IsTrackingPointer(pointer_id) || | |
| 331 !pointer_targets_[pointer_id].is_pointer_down) { | |
| 332 const bool any_pointers_down = AreAnyPointersDown(); | |
| 333 UpdateTargetForPointer(pointer_id, event); | |
| 334 if (is_mouse_event) | |
| 335 mouse_cursor_source_window_ = pointer_targets_[pointer_id].window; | |
| 336 | |
| 337 PointerTarget& pointer_target = pointer_targets_[pointer_id]; | |
| 338 if (pointer_target.is_pointer_down) { | |
| 339 if (is_mouse_event) | |
| 340 mouse_cursor_source_window_ = pointer_target.window; | |
| 341 if (!any_pointers_down) { | |
| 342 delegate_->SetFocusedWindowFromEventDispatcher(pointer_target.window); | |
| 343 delegate_->SetNativeCapture(pointer_target.window); | |
| 344 } | |
| 345 } | |
| 346 } | |
| 347 | |
| 348 // When we release the mouse button, we want the cursor to be sourced from | |
| 349 // the window under the mouse pointer, even though we're sending the button | |
| 350 // up event to the window that had implicit capture. We have to set this | |
| 351 // before we perform dispatch because the Delegate is going to read this | |
| 352 // information from us. | |
| 353 if (is_pointer_going_up && is_mouse_event) | |
| 354 UpdateCursorProviderByLastKnownLocation(); | |
| 355 | |
| 356 DispatchToPointerTarget(pointer_targets_[pointer_id], event); | |
| 357 | |
| 358 if (is_pointer_going_up) { | |
| 359 if (is_mouse_event) | |
| 360 pointer_targets_[pointer_id].is_pointer_down = false; | |
| 361 else | |
| 362 StopTrackingPointer(pointer_id); | |
| 363 if (!AreAnyPointersDown()) | |
| 364 delegate_->ReleaseNativeCapture(); | |
| 365 } | |
| 366 } | |
| 367 | |
| 368 void EventDispatcher::StartTrackingPointer( | |
| 369 int32_t pointer_id, | |
| 370 const PointerTarget& pointer_target) { | |
| 371 DCHECK(!IsTrackingPointer(pointer_id)); | |
| 372 ObserveWindow(pointer_target.window); | |
| 373 pointer_targets_[pointer_id] = pointer_target; | |
| 374 } | |
| 375 | |
| 376 void EventDispatcher::StopTrackingPointer(int32_t pointer_id) { | |
| 377 DCHECK(IsTrackingPointer(pointer_id)); | |
| 378 ServerWindow* window = pointer_targets_[pointer_id].window; | |
| 379 pointer_targets_.erase(pointer_id); | |
| 380 if (window) | |
| 381 UnobserveWindow(window); | |
| 382 } | |
| 383 | |
| 384 void EventDispatcher::UpdateTargetForPointer(int32_t pointer_id, | |
| 385 const ui::LocatedEvent& event) { | |
| 386 if (!IsTrackingPointer(pointer_id)) { | |
| 387 StartTrackingPointer(pointer_id, PointerTargetForEvent(event)); | |
| 388 return; | |
| 389 } | |
| 390 | |
| 391 const PointerTarget pointer_target = PointerTargetForEvent(event); | |
| 392 if (pointer_target.window == pointer_targets_[pointer_id].window && | |
| 393 pointer_target.in_nonclient_area == | |
| 394 pointer_targets_[pointer_id].in_nonclient_area) { | |
| 395 // The targets are the same, only set the down state to true if necessary. | |
| 396 // Down going to up is handled by ProcessLocatedEvent(). | |
| 397 if (pointer_target.is_pointer_down) | |
| 398 pointer_targets_[pointer_id].is_pointer_down = true; | |
| 399 return; | |
| 400 } | |
| 401 | |
| 402 // The targets are changing. Send an exit if appropriate. | |
| 403 if (event.IsMousePointerEvent()) { | |
| 404 ui::PointerEvent exit_event( | |
| 405 ui::ET_POINTER_EXITED, event.location(), event.root_location(), | |
| 406 event.flags(), ui::PointerEvent::kMousePointerId, | |
| 407 ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_MOUSE), | |
| 408 event.time_stamp()); | |
| 409 DispatchToPointerTarget(pointer_targets_[pointer_id], exit_event); | |
| 410 } | |
| 411 | |
| 412 // Technically we're updating in place, but calling start then stop makes for | |
| 413 // simpler code. | |
| 414 StopTrackingPointer(pointer_id); | |
| 415 StartTrackingPointer(pointer_id, pointer_target); | |
| 416 } | |
| 417 | |
| 418 EventDispatcher::PointerTarget EventDispatcher::PointerTargetForEvent( | |
| 419 const ui::LocatedEvent& event) { | |
| 420 PointerTarget pointer_target; | |
| 421 gfx::Point location(event.location()); | |
| 422 ServerWindow* target_window = FindDeepestVisibleWindowForEvents(&location); | |
| 423 pointer_target.window = | |
| 424 modal_window_controller_.GetTargetForWindow(target_window); | |
| 425 pointer_target.is_mouse_event = event.IsMousePointerEvent(); | |
| 426 pointer_target.in_nonclient_area = | |
| 427 target_window != pointer_target.window || | |
| 428 IsLocationInNonclientArea(pointer_target.window, location); | |
| 429 pointer_target.is_pointer_down = event.type() == ui::ET_POINTER_DOWN; | |
| 430 return pointer_target; | |
| 431 } | |
| 432 | |
| 433 bool EventDispatcher::AreAnyPointersDown() const { | |
| 434 for (const auto& pair : pointer_targets_) { | |
| 435 if (pair.second.is_pointer_down) | |
| 436 return true; | |
| 437 } | |
| 438 return false; | |
| 439 } | |
| 440 | |
| 441 void EventDispatcher::DispatchToPointerTarget(const PointerTarget& target, | |
| 442 const ui::LocatedEvent& event) { | |
| 443 if (!target.window) { | |
| 444 delegate_->OnEventTargetNotFound(event); | |
| 445 return; | |
| 446 } | |
| 447 | |
| 448 if (target.is_mouse_event) | |
| 449 mouse_cursor_in_non_client_area_ = target.in_nonclient_area; | |
| 450 | |
| 451 DispatchToClient(target.window, delegate_->GetEventTargetClientId( | |
| 452 target.window, target.in_nonclient_area), | |
| 453 event); | |
| 454 } | |
| 455 | |
| 456 void EventDispatcher::DispatchToClient(ServerWindow* window, | |
| 457 ClientSpecificId client_id, | |
| 458 const ui::LocatedEvent& event) { | |
| 459 gfx::Point location(event.location()); | |
| 460 gfx::Transform transform(GetTransformToWindow(window)); | |
| 461 transform.TransformPoint(&location); | |
| 462 std::unique_ptr<ui::Event> clone = ui::Event::Clone(event); | |
| 463 clone->AsLocatedEvent()->set_location(location); | |
| 464 // TODO(jonross): add post-target accelerator support once accelerators | |
| 465 // support pointer events. | |
| 466 delegate_->DispatchInputEventToWindow(window, client_id, *clone, nullptr); | |
| 467 } | |
| 468 | |
| 469 void EventDispatcher::CancelPointerEventsToTarget(ServerWindow* window) { | |
| 470 if (capture_window_ == window) { | |
| 471 UnobserveWindow(window); | |
| 472 capture_window_ = nullptr; | |
| 473 capture_window_client_id_ = kInvalidClientId; | |
| 474 mouse_button_down_ = false; | |
| 475 // A window only cares to be informed that it lost capture if it explicitly | |
| 476 // requested capture. A window can lose capture if another window gains | |
| 477 // explicit capture. | |
| 478 delegate_->OnServerWindowCaptureLost(window); | |
| 479 delegate_->ReleaseNativeCapture(); | |
| 480 UpdateCursorProviderByLastKnownLocation(); | |
| 481 return; | |
| 482 } | |
| 483 | |
| 484 for (auto& pair : pointer_targets_) { | |
| 485 if (pair.second.window == window) { | |
| 486 UnobserveWindow(window); | |
| 487 pair.second.window = nullptr; | |
| 488 } | |
| 489 } | |
| 490 } | |
| 491 | |
| 492 void EventDispatcher::ObserveWindow(ServerWindow* window) { | |
| 493 auto res = observed_windows_.insert(std::make_pair(window, 0u)); | |
| 494 res.first->second++; | |
| 495 if (res.second) | |
| 496 window->AddObserver(this); | |
| 497 } | |
| 498 | |
| 499 void EventDispatcher::UnobserveWindow(ServerWindow* window) { | |
| 500 auto it = observed_windows_.find(window); | |
| 501 DCHECK(it != observed_windows_.end()); | |
| 502 DCHECK_LT(0u, it->second); | |
| 503 it->second--; | |
| 504 if (!it->second) { | |
| 505 window->RemoveObserver(this); | |
| 506 observed_windows_.erase(it); | |
| 507 } | |
| 508 } | |
| 509 | |
| 510 Accelerator* EventDispatcher::FindAccelerator( | |
| 511 const ui::KeyEvent& event, | |
| 512 const ui::mojom::AcceleratorPhase phase) { | |
| 513 for (const auto& pair : accelerators_) { | |
| 514 if (pair.second->MatchesEvent(event, phase)) { | |
| 515 return pair.second.get(); | |
| 516 } | |
| 517 } | |
| 518 return nullptr; | |
| 519 } | |
| 520 | |
| 521 ServerWindow* EventDispatcher::FindDeepestVisibleWindowForEvents( | |
| 522 gfx::Point* location) { | |
| 523 ServerWindow* root = delegate_->GetRootWindowContaining(*location); | |
| 524 if (!root) | |
| 525 return nullptr; | |
| 526 | |
| 527 return mus::ws::FindDeepestVisibleWindowForEvents(root, location); | |
| 528 } | |
| 529 | |
| 530 void EventDispatcher::OnWillChangeWindowHierarchy(ServerWindow* window, | |
| 531 ServerWindow* new_parent, | |
| 532 ServerWindow* old_parent) { | |
| 533 // TODO(sky): moving to a different root likely needs to transfer capture. | |
| 534 // TODO(sky): this isn't quite right, I think the logic should be (assuming | |
| 535 // moving in same root and still drawn): | |
| 536 // . if there is capture and window is still in the same root, continue | |
| 537 // sending to it. | |
| 538 // . if there isn't capture, then reevaluate each of the pointer targets | |
| 539 // sending exit as necessary. | |
| 540 // http://crbug.com/613646 . | |
| 541 if (!new_parent || !new_parent->IsDrawn() || | |
| 542 new_parent->GetRoot() != old_parent->GetRoot()) { | |
| 543 CancelPointerEventsToTarget(window); | |
| 544 } | |
| 545 } | |
| 546 | |
| 547 void EventDispatcher::OnWindowVisibilityChanged(ServerWindow* window) { | |
| 548 CancelPointerEventsToTarget(window); | |
| 549 } | |
| 550 | |
| 551 void EventDispatcher::OnWindowDestroyed(ServerWindow* window) { | |
| 552 CancelPointerEventsToTarget(window); | |
| 553 | |
| 554 if (mouse_cursor_source_window_ == window) | |
| 555 mouse_cursor_source_window_ = nullptr; | |
| 556 } | |
| 557 | |
| 558 } // namespace ws | |
| 559 } // namespace mus | |
| OLD | NEW |