| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/mus/ws/event_dispatcher.h" | 5 #include "components/mus/ws/event_dispatcher.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/time/time.h" | 9 #include "base/time/time.h" |
| 10 #include "components/mus/ws/accelerator.h" | 10 #include "components/mus/ws/accelerator.h" |
| 11 #include "components/mus/ws/display.h" | 11 #include "components/mus/ws/display.h" |
| 12 #include "components/mus/ws/event_dispatcher_delegate.h" | 12 #include "components/mus/ws/event_dispatcher_delegate.h" |
| 13 #include "components/mus/ws/server_window.h" | 13 #include "components/mus/ws/server_window.h" |
| 14 #include "components/mus/ws/server_window_delegate.h" | 14 #include "components/mus/ws/server_window_delegate.h" |
| 15 #include "components/mus/ws/window_coordinate_conversions.h" | 15 #include "components/mus/ws/window_coordinate_conversions.h" |
| 16 #include "components/mus/ws/window_finder.h" | 16 #include "components/mus/ws/window_finder.h" |
| 17 #include "ui/events/event_utils.h" | 17 #include "ui/events/event_utils.h" |
| 18 #include "ui/gfx/geometry/point.h" | 18 #include "ui/gfx/geometry/point.h" |
| 19 #include "ui/gfx/geometry/point_conversions.h" | 19 #include "ui/gfx/geometry/point_conversions.h" |
| 20 | 20 |
| 21 namespace mus { | 21 namespace mus { |
| 22 namespace ws { | 22 namespace ws { |
| 23 |
| 24 using Entry = std::pair<uint32_t, std::unique_ptr<Accelerator>>; |
| 25 |
| 23 namespace { | 26 namespace { |
| 24 | 27 |
| 25 bool IsOnlyOneMouseButtonDown(int flags) { | 28 bool IsOnlyOneMouseButtonDown(int flags) { |
| 26 const uint32_t button_only_flags = | 29 const uint32_t button_only_flags = |
| 27 flags & (ui::EF_LEFT_MOUSE_BUTTON | ui::EF_MIDDLE_MOUSE_BUTTON | | 30 flags & (ui::EF_LEFT_MOUSE_BUTTON | ui::EF_MIDDLE_MOUSE_BUTTON | |
| 28 ui::EF_RIGHT_MOUSE_BUTTON); | 31 ui::EF_RIGHT_MOUSE_BUTTON); |
| 29 return button_only_flags == ui::EF_LEFT_MOUSE_BUTTON || | 32 return button_only_flags == ui::EF_LEFT_MOUSE_BUTTON || |
| 30 button_only_flags == ui::EF_MIDDLE_MOUSE_BUTTON || | 33 button_only_flags == ui::EF_MIDDLE_MOUSE_BUTTON || |
| 31 button_only_flags == ui::EF_RIGHT_MOUSE_BUTTON; | 34 button_only_flags == ui::EF_RIGHT_MOUSE_BUTTON; |
| 32 } | 35 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 58 NOTREACHED(); | 61 NOTREACHED(); |
| 59 return 0; | 62 return 0; |
| 60 } | 63 } |
| 61 | 64 |
| 62 } // namespace | 65 } // namespace |
| 63 | 66 |
| 64 //////////////////////////////////////////////////////////////////////////////// | 67 //////////////////////////////////////////////////////////////////////////////// |
| 65 | 68 |
| 66 EventDispatcher::EventDispatcher(EventDispatcherDelegate* delegate) | 69 EventDispatcher::EventDispatcher(EventDispatcherDelegate* delegate) |
| 67 : delegate_(delegate), | 70 : delegate_(delegate), |
| 68 root_(nullptr), | |
| 69 capture_window_(nullptr), | 71 capture_window_(nullptr), |
| 70 capture_window_client_id_(kInvalidClientId), | 72 capture_window_client_id_(kInvalidClientId), |
| 71 modal_window_controller_(this), | 73 modal_window_controller_(this), |
| 72 mouse_button_down_(false), | 74 mouse_button_down_(false), |
| 73 mouse_cursor_source_window_(nullptr), | 75 mouse_cursor_source_window_(nullptr), |
| 74 mouse_cursor_in_non_client_area_(false) {} | 76 mouse_cursor_in_non_client_area_(false) {} |
| 75 | 77 |
| 76 EventDispatcher::~EventDispatcher() { | 78 EventDispatcher::~EventDispatcher() { |
| 77 if (capture_window_) { | 79 if (capture_window_) { |
| 78 UnobserveWindow(capture_window_); | 80 UnobserveWindow(capture_window_); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 | 166 |
| 165 // Set the capture before changing native capture; otherwise, the callback | 167 // Set the capture before changing native capture; otherwise, the callback |
| 166 // from native platform might try to set the capture again. | 168 // from native platform might try to set the capture again. |
| 167 bool had_capture_window = capture_window_ != nullptr; | 169 bool had_capture_window = capture_window_ != nullptr; |
| 168 capture_window_ = window; | 170 capture_window_ = window; |
| 169 capture_window_client_id_ = client_id; | 171 capture_window_client_id_ = client_id; |
| 170 | 172 |
| 171 // Begin tracking the capture window if it is not yet being observed. | 173 // Begin tracking the capture window if it is not yet being observed. |
| 172 if (window) { | 174 if (window) { |
| 173 ObserveWindow(window); | 175 ObserveWindow(window); |
| 176 // TODO(sky): this conditional is problematic for the case of capture moving |
| 177 // to a different display. |
| 174 if (!had_capture_window) | 178 if (!had_capture_window) |
| 175 delegate_->SetNativeCapture(); | 179 delegate_->SetNativeCapture(window); |
| 176 } else { | 180 } else { |
| 177 delegate_->ReleaseNativeCapture(); | 181 delegate_->ReleaseNativeCapture(); |
| 178 if (!mouse_button_down_) | 182 if (!mouse_button_down_) |
| 179 UpdateCursorProviderByLastKnownLocation(); | 183 UpdateCursorProviderByLastKnownLocation(); |
| 180 } | 184 } |
| 181 | 185 |
| 182 return true; | 186 return true; |
| 183 } | 187 } |
| 184 | 188 |
| 185 void EventDispatcher::AddSystemModalWindow(ServerWindow* window) { | 189 void EventDispatcher::AddSystemModalWindow(ServerWindow* window) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 201 if (!capture_window_) | 205 if (!capture_window_) |
| 202 return; | 206 return; |
| 203 | 207 |
| 204 if (modal_window_controller_.IsWindowBlocked(capture_window_)) | 208 if (modal_window_controller_.IsWindowBlocked(capture_window_)) |
| 205 SetCaptureWindow(nullptr, kInvalidClientId); | 209 SetCaptureWindow(nullptr, kInvalidClientId); |
| 206 } | 210 } |
| 207 | 211 |
| 208 void EventDispatcher::UpdateNonClientAreaForCurrentWindow() { | 212 void EventDispatcher::UpdateNonClientAreaForCurrentWindow() { |
| 209 if (mouse_cursor_source_window_) { | 213 if (mouse_cursor_source_window_) { |
| 210 gfx::Point location = mouse_pointer_last_location_; | 214 gfx::Point location = mouse_pointer_last_location_; |
| 211 ServerWindow* target = FindDeepestVisibleWindowForEvents(root_, &location); | 215 ServerWindow* target = FindDeepestVisibleWindowForEvents(&location); |
| 212 if (target == mouse_cursor_source_window_) { | 216 if (target == mouse_cursor_source_window_) { |
| 213 mouse_cursor_in_non_client_area_ = | 217 mouse_cursor_in_non_client_area_ = |
| 214 mouse_cursor_source_window_ | 218 mouse_cursor_source_window_ |
| 215 ? IsLocationInNonclientArea(mouse_cursor_source_window_, location) | 219 ? IsLocationInNonclientArea(mouse_cursor_source_window_, location) |
| 216 : false; | 220 : false; |
| 217 } | 221 } |
| 218 } | 222 } |
| 219 } | 223 } |
| 220 | 224 |
| 221 void EventDispatcher::UpdateCursorProviderByLastKnownLocation() { | 225 void EventDispatcher::UpdateCursorProviderByLastKnownLocation() { |
| 222 if (!mouse_button_down_) { | 226 if (!mouse_button_down_) { |
| 223 gfx::Point location = mouse_pointer_last_location_; | 227 gfx::Point location = mouse_pointer_last_location_; |
| 224 mouse_cursor_source_window_ = | 228 mouse_cursor_source_window_ = FindDeepestVisibleWindowForEvents(&location); |
| 225 FindDeepestVisibleWindowForEvents(root_, &location); | |
| 226 | 229 |
| 227 mouse_cursor_in_non_client_area_ = | 230 mouse_cursor_in_non_client_area_ = |
| 228 mouse_cursor_source_window_ | 231 mouse_cursor_source_window_ |
| 229 ? IsLocationInNonclientArea(mouse_cursor_source_window_, location) | 232 ? IsLocationInNonclientArea(mouse_cursor_source_window_, location) |
| 230 : false; | 233 : false; |
| 231 } | 234 } |
| 232 } | 235 } |
| 233 | 236 |
| 234 bool EventDispatcher::AddAccelerator(uint32_t id, | 237 bool EventDispatcher::AddAccelerator(uint32_t id, |
| 235 mojom::EventMatcherPtr event_matcher) { | 238 mojom::EventMatcherPtr event_matcher) { |
| 236 std::unique_ptr<Accelerator> accelerator(new Accelerator(id, *event_matcher)); | 239 std::unique_ptr<Accelerator> accelerator(new Accelerator(id, *event_matcher)); |
| 237 // If an accelerator with the same id or matcher already exists, then abort. | 240 // If an accelerator with the same id or matcher already exists, then abort. |
| 238 for (const auto& pair : accelerators_) { | 241 for (const auto& pair : accelerators_) { |
| 239 if (pair.first == id || accelerator->EqualEventMatcher(pair.second.get())) | 242 if (pair.first == id || accelerator->EqualEventMatcher(pair.second.get())) |
| 240 return false; | 243 return false; |
| 241 } | 244 } |
| 242 accelerators_.insert(Entry(id, std::move(accelerator))); | 245 accelerators_.insert(Entry(id, std::move(accelerator))); |
| 243 return true; | 246 return true; |
| 244 } | 247 } |
| 245 | 248 |
| 246 void EventDispatcher::RemoveAccelerator(uint32_t id) { | 249 void EventDispatcher::RemoveAccelerator(uint32_t id) { |
| 247 auto it = accelerators_.find(id); | 250 auto it = accelerators_.find(id); |
| 248 // Clients may pass bogus ids. | 251 // Clients may pass bogus ids. |
| 249 if (it != accelerators_.end()) | 252 if (it != accelerators_.end()) |
| 250 accelerators_.erase(it); | 253 accelerators_.erase(it); |
| 251 } | 254 } |
| 252 | 255 |
| 253 void EventDispatcher::ProcessEvent(const ui::Event& event) { | 256 void EventDispatcher::ProcessEvent(const ui::Event& event) { |
| 254 if (!root_) // Tests may not have a root window. | |
| 255 return; | |
| 256 | |
| 257 if (event.IsKeyEvent()) { | 257 if (event.IsKeyEvent()) { |
| 258 const ui::KeyEvent* key_event = event.AsKeyEvent(); | 258 const ui::KeyEvent* key_event = event.AsKeyEvent(); |
| 259 if (event.type() == ui::ET_KEY_PRESSED && !key_event->is_char()) { | 259 if (event.type() == ui::ET_KEY_PRESSED && !key_event->is_char()) { |
| 260 Accelerator* pre_target = | 260 Accelerator* pre_target = |
| 261 FindAccelerator(*key_event, ui::mojom::AcceleratorPhase::PRE_TARGET); | 261 FindAccelerator(*key_event, ui::mojom::AcceleratorPhase::PRE_TARGET); |
| 262 if (pre_target) { | 262 if (pre_target) { |
| 263 delegate_->OnAccelerator(pre_target->id(), event); | 263 delegate_->OnAccelerator(pre_target->id(), event); |
| 264 return; | 264 return; |
| 265 } | 265 } |
| 266 } | 266 } |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 333 UpdateTargetForPointer(pointer_id, event); | 333 UpdateTargetForPointer(pointer_id, event); |
| 334 if (is_mouse_event) | 334 if (is_mouse_event) |
| 335 mouse_cursor_source_window_ = pointer_targets_[pointer_id].window; | 335 mouse_cursor_source_window_ = pointer_targets_[pointer_id].window; |
| 336 | 336 |
| 337 PointerTarget& pointer_target = pointer_targets_[pointer_id]; | 337 PointerTarget& pointer_target = pointer_targets_[pointer_id]; |
| 338 if (pointer_target.is_pointer_down) { | 338 if (pointer_target.is_pointer_down) { |
| 339 if (is_mouse_event) | 339 if (is_mouse_event) |
| 340 mouse_cursor_source_window_ = pointer_target.window; | 340 mouse_cursor_source_window_ = pointer_target.window; |
| 341 if (!any_pointers_down) { | 341 if (!any_pointers_down) { |
| 342 delegate_->SetFocusedWindowFromEventDispatcher(pointer_target.window); | 342 delegate_->SetFocusedWindowFromEventDispatcher(pointer_target.window); |
| 343 delegate_->SetNativeCapture(); | 343 delegate_->SetNativeCapture(pointer_target.window); |
| 344 } | 344 } |
| 345 } | 345 } |
| 346 } | 346 } |
| 347 | 347 |
| 348 // When we release the mouse button, we want the cursor to be sourced from | 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 | 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 | 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 | 351 // before we perform dispatch because the Delegate is going to read this |
| 352 // information from us. | 352 // information from us. |
| 353 if (is_pointer_going_up && is_mouse_event) | 353 if (is_pointer_going_up && is_mouse_event) |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 409 DispatchToPointerTarget(pointer_targets_[pointer_id], exit_event); | 409 DispatchToPointerTarget(pointer_targets_[pointer_id], exit_event); |
| 410 } | 410 } |
| 411 | 411 |
| 412 // Technically we're updating in place, but calling start then stop makes for | 412 // Technically we're updating in place, but calling start then stop makes for |
| 413 // simpler code. | 413 // simpler code. |
| 414 StopTrackingPointer(pointer_id); | 414 StopTrackingPointer(pointer_id); |
| 415 StartTrackingPointer(pointer_id, pointer_target); | 415 StartTrackingPointer(pointer_id, pointer_target); |
| 416 } | 416 } |
| 417 | 417 |
| 418 EventDispatcher::PointerTarget EventDispatcher::PointerTargetForEvent( | 418 EventDispatcher::PointerTarget EventDispatcher::PointerTargetForEvent( |
| 419 const ui::LocatedEvent& event) const { | 419 const ui::LocatedEvent& event) { |
| 420 PointerTarget pointer_target; | 420 PointerTarget pointer_target; |
| 421 gfx::Point location(event.location()); | 421 gfx::Point location(event.location()); |
| 422 ServerWindow* target_window = | 422 ServerWindow* target_window = FindDeepestVisibleWindowForEvents(&location); |
| 423 FindDeepestVisibleWindowForEvents(root_, &location); | |
| 424 pointer_target.window = | 423 pointer_target.window = |
| 425 modal_window_controller_.GetTargetForWindow(target_window); | 424 modal_window_controller_.GetTargetForWindow(target_window); |
| 426 pointer_target.is_mouse_event = event.IsMousePointerEvent(); | 425 pointer_target.is_mouse_event = event.IsMousePointerEvent(); |
| 427 pointer_target.in_nonclient_area = | 426 pointer_target.in_nonclient_area = |
| 428 target_window != pointer_target.window || | 427 target_window != pointer_target.window || |
| 429 IsLocationInNonclientArea(pointer_target.window, location); | 428 IsLocationInNonclientArea(pointer_target.window, location); |
| 430 pointer_target.is_pointer_down = event.type() == ui::ET_POINTER_DOWN; | 429 pointer_target.is_pointer_down = event.type() == ui::ET_POINTER_DOWN; |
| 431 return pointer_target; | 430 return pointer_target; |
| 432 } | 431 } |
| 433 | 432 |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 512 const ui::KeyEvent& event, | 511 const ui::KeyEvent& event, |
| 513 const ui::mojom::AcceleratorPhase phase) { | 512 const ui::mojom::AcceleratorPhase phase) { |
| 514 for (const auto& pair : accelerators_) { | 513 for (const auto& pair : accelerators_) { |
| 515 if (pair.second->MatchesEvent(event, phase)) { | 514 if (pair.second->MatchesEvent(event, phase)) { |
| 516 return pair.second.get(); | 515 return pair.second.get(); |
| 517 } | 516 } |
| 518 } | 517 } |
| 519 return nullptr; | 518 return nullptr; |
| 520 } | 519 } |
| 521 | 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 |
| 522 void EventDispatcher::OnWillChangeWindowHierarchy(ServerWindow* window, | 530 void EventDispatcher::OnWillChangeWindowHierarchy(ServerWindow* window, |
| 523 ServerWindow* new_parent, | 531 ServerWindow* new_parent, |
| 524 ServerWindow* old_parent) { | 532 ServerWindow* old_parent) { |
| 525 // TODO(sky): moving to a different root likely needs to transfer capture. | 533 // TODO(sky): moving to a different root likely needs to transfer capture. |
| 526 // TODO(sky): this isn't quite right, I think the logic should be (assuming | 534 // TODO(sky): this isn't quite right, I think the logic should be (assuming |
| 527 // moving in same root and still drawn): | 535 // moving in same root and still drawn): |
| 528 // . if there is capture and window is still in the same root, continue | 536 // . if there is capture and window is still in the same root, continue |
| 529 // sending to it. | 537 // sending to it. |
| 530 // . if there isn't capture, then reevaluate each of the pointer targets | 538 // . if there isn't capture, then reevaluate each of the pointer targets |
| 531 // sending exit as necessary. | 539 // sending exit as necessary. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 542 | 550 |
| 543 void EventDispatcher::OnWindowDestroyed(ServerWindow* window) { | 551 void EventDispatcher::OnWindowDestroyed(ServerWindow* window) { |
| 544 CancelPointerEventsToTarget(window); | 552 CancelPointerEventsToTarget(window); |
| 545 | 553 |
| 546 if (mouse_cursor_source_window_ == window) | 554 if (mouse_cursor_source_window_ == window) |
| 547 mouse_cursor_source_window_ = nullptr; | 555 mouse_cursor_source_window_ = nullptr; |
| 548 } | 556 } |
| 549 | 557 |
| 550 } // namespace ws | 558 } // namespace ws |
| 551 } // namespace mus | 559 } // namespace mus |
| OLD | NEW |