| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 #import <Cocoa/Cocoa.h> | 5 #import <Cocoa/Cocoa.h> |
| 6 #include <stddef.h> | 6 #include <stddef.h> |
| 7 | 7 |
| 8 #import "base/mac/scoped_nsobject.h" | 8 #import "base/mac/scoped_nsobject.h" |
| 9 #import "base/mac/scoped_objc_class_swizzler.h" | 9 #import "base/mac/scoped_objc_class_swizzler.h" |
| 10 #include "base/macros.h" | 10 #include "base/macros.h" |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 252 // Overridden from ui::EventTarget: | 252 // Overridden from ui::EventTarget: |
| 253 bool CanAcceptEvent(const ui::Event& event) override { return true; } | 253 bool CanAcceptEvent(const ui::Event& event) override { return true; } |
| 254 ui::EventTarget* GetParentTarget() override { return nullptr; } | 254 ui::EventTarget* GetParentTarget() override { return nullptr; } |
| 255 std::unique_ptr<ui::EventTargetIterator> GetChildIterator() const override; | 255 std::unique_ptr<ui::EventTargetIterator> GetChildIterator() const override; |
| 256 ui::EventTargeter* GetEventTargeter() override { return this; } | 256 ui::EventTargeter* GetEventTargeter() override { return this; } |
| 257 | 257 |
| 258 // Overridden from ui::EventHandler: | 258 // Overridden from ui::EventHandler: |
| 259 void OnMouseEvent(ui::MouseEvent* event) override; | 259 void OnMouseEvent(ui::MouseEvent* event) override; |
| 260 void OnKeyEvent(ui::KeyEvent* event) override; | 260 void OnKeyEvent(ui::KeyEvent* event) override; |
| 261 void OnTouchEvent(ui::TouchEvent* event) override; | 261 void OnTouchEvent(ui::TouchEvent* event) override; |
| 262 void OnScrollEvent(ui::ScrollEvent* event) override; |
| 262 | 263 |
| 263 // Overridden from ui::EventSource: | 264 // Overridden from ui::EventSource: |
| 264 ui::EventProcessor* GetEventProcessor() override { return this; } | 265 ui::EventProcessor* GetEventProcessor() override { return this; } |
| 265 | 266 |
| 266 // Overridden from ui::EventProcessor: | 267 // Overridden from ui::EventProcessor: |
| 267 ui::EventTarget* GetRootTarget() override { return this; } | 268 ui::EventTarget* GetRootTarget() override { return this; } |
| 268 | 269 |
| 269 // Overridden from ui::EventDispatcherDelegate (via ui::EventProcessor): | 270 // Overridden from ui::EventDispatcherDelegate (via ui::EventProcessor): |
| 270 bool CanDispatchToTarget(EventTarget* target) override { return true; } | 271 bool CanDispatchToTarget(EventTarget* target) override { return true; } |
| 271 | 272 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 311 EventGeneratorDelegateMac(); | 312 EventGeneratorDelegateMac(); |
| 312 ~EventGeneratorDelegateMac() override; | 313 ~EventGeneratorDelegateMac() override; |
| 313 | 314 |
| 314 ui::test::EventGenerator* owner_; | 315 ui::test::EventGenerator* owner_; |
| 315 base::scoped_nsobject<NSWindow> window_; | 316 base::scoped_nsobject<NSWindow> window_; |
| 316 std::unique_ptr<base::mac::ScopedObjCClassSwizzler> swizzle_pressed_; | 317 std::unique_ptr<base::mac::ScopedObjCClassSwizzler> swizzle_pressed_; |
| 317 std::unique_ptr<base::mac::ScopedObjCClassSwizzler> swizzle_location_; | 318 std::unique_ptr<base::mac::ScopedObjCClassSwizzler> swizzle_location_; |
| 318 std::unique_ptr<base::mac::ScopedObjCClassSwizzler> swizzle_current_event_; | 319 std::unique_ptr<base::mac::ScopedObjCClassSwizzler> swizzle_current_event_; |
| 319 base::scoped_nsobject<NSMenu> fake_menu_; | 320 base::scoped_nsobject<NSMenu> fake_menu_; |
| 320 | 321 |
| 322 // Mac always sends trackpad scroll events between begin/end phase event |
| 323 // markers. If |in_trackpad_scroll| is false, a phase begin event is sent |
| 324 // before any trackpad scroll update. |
| 325 bool in_trackpad_scroll = false; |
| 326 |
| 327 // Timestamp on the last scroll update, used to simulate scroll momentum. |
| 328 base::TimeTicks last_scroll_timestamp_; |
| 329 |
| 321 DISALLOW_COPY_AND_ASSIGN(EventGeneratorDelegateMac); | 330 DISALLOW_COPY_AND_ASSIGN(EventGeneratorDelegateMac); |
| 322 }; | 331 }; |
| 323 | 332 |
| 324 EventGeneratorDelegateMac::EventGeneratorDelegateMac() : owner_(nullptr) { | 333 EventGeneratorDelegateMac::EventGeneratorDelegateMac() : owner_(nullptr) { |
| 325 DCHECK(!ui::test::EventGenerator::default_delegate); | 334 DCHECK(!ui::test::EventGenerator::default_delegate); |
| 326 ui::test::EventGenerator::default_delegate = this; | 335 ui::test::EventGenerator::default_delegate = this; |
| 327 SetTargetHandler(this); | 336 SetTargetHandler(this); |
| 328 // Install a fake "edit" menu. This is normally provided by Chrome's | 337 // Install a fake "edit" menu. This is normally provided by Chrome's |
| 329 // MainMenu.xib, but src/ui shouldn't depend on that. | 338 // MainMenu.xib, but src/ui shouldn't depend on that. |
| 330 fake_menu_.reset([[NSMenu alloc] initWithTitle:@"Edit"]); | 339 fake_menu_.reset([[NSMenu alloc] initWithTitle:@"Edit"]); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 385 if ([fake_menu_ performKeyEquivalent:ns_event]) | 394 if ([fake_menu_ performKeyEquivalent:ns_event]) |
| 386 return; | 395 return; |
| 387 | 396 |
| 388 EmulateSendEvent(window_, ns_event); | 397 EmulateSendEvent(window_, ns_event); |
| 389 } | 398 } |
| 390 | 399 |
| 391 void EventGeneratorDelegateMac::OnTouchEvent(ui::TouchEvent* event) { | 400 void EventGeneratorDelegateMac::OnTouchEvent(ui::TouchEvent* event) { |
| 392 NOTREACHED() << "Touchscreen events not supported on Chrome Mac."; | 401 NOTREACHED() << "Touchscreen events not supported on Chrome Mac."; |
| 393 } | 402 } |
| 394 | 403 |
| 404 void EventGeneratorDelegateMac::OnScrollEvent(ui::ScrollEvent* event) { |
| 405 // Ignore FLING_CANCEL. Cocoa provides a continuous stream of events during a |
| 406 // fling. For now, this method simulates a momentum stream using a single |
| 407 // update with a momentum phase (plus begin/end phase events), triggered when |
| 408 // the EventGenerator requests a FLING_START. |
| 409 if (event->type() == ui::ET_SCROLL_FLING_CANCEL) |
| 410 return; |
| 411 |
| 412 NSPoint location = ConvertRootPointToTarget(window_, event->location()); |
| 413 |
| 414 // MAY_BEGIN/END comes from the EventGenerator for trackpad rests. |
| 415 if (event->momentum_phase() == ui::EventMomentumPhase::MAY_BEGIN || |
| 416 event->momentum_phase() == ui::EventMomentumPhase::END) { |
| 417 DCHECK_EQ(0, event->x_offset()); |
| 418 DCHECK_EQ(0, event->y_offset()); |
| 419 NSEventPhase phase = |
| 420 event->momentum_phase() == ui::EventMomentumPhase::MAY_BEGIN |
| 421 ? NSEventPhaseMayBegin |
| 422 : NSEventPhaseCancelled; |
| 423 |
| 424 NSEvent* rest = cocoa_test_event_utils::TestScrollEvent( |
| 425 location, window_, 0, 0, true, phase, NSEventPhaseNone); |
| 426 EmulateSendEvent(window_, rest); |
| 427 |
| 428 // Allow the next ScrollSequence to skip the "begin". |
| 429 in_trackpad_scroll = phase == NSEventPhaseMayBegin; |
| 430 return; |
| 431 } |
| 432 |
| 433 NSEventPhase event_phase = NSEventPhaseBegan; |
| 434 NSEventPhase momentum_phase = NSEventPhaseNone; |
| 435 |
| 436 // Treat FLING_START as the beginning of a momentum phase. |
| 437 if (event->type() == ui::ET_SCROLL_FLING_START) { |
| 438 DCHECK(in_trackpad_scroll); |
| 439 // First end the non-momentum phase. |
| 440 NSEvent* end = cocoa_test_event_utils::TestScrollEvent( |
| 441 location, window_, 0, 0, true, NSEventPhaseEnded, NSEventPhaseNone); |
| 442 EmulateSendEvent(window_, end); |
| 443 in_trackpad_scroll = false; |
| 444 |
| 445 // Assume a zero time delta means no fling. Just end the event phase. |
| 446 if (event->time_stamp() == last_scroll_timestamp_) |
| 447 return; |
| 448 |
| 449 // Otherwise, switch phases for the "fling". |
| 450 std::swap(event_phase, momentum_phase); |
| 451 } |
| 452 |
| 453 // Send a begin for the current event phase, unless it's already in progress. |
| 454 if (!in_trackpad_scroll) { |
| 455 NSEvent* begin = cocoa_test_event_utils::TestScrollEvent( |
| 456 location, window_, 0, 0, true, event_phase, momentum_phase); |
| 457 EmulateSendEvent(window_, begin); |
| 458 in_trackpad_scroll = true; |
| 459 } |
| 460 |
| 461 if (event->type() == ui::ET_SCROLL) { |
| 462 NSEvent* update = cocoa_test_event_utils::TestScrollEvent( |
| 463 location, window_, -event->x_offset(), -event->y_offset(), true, |
| 464 NSEventPhaseChanged, NSEventPhaseNone); |
| 465 EmulateSendEvent(window_, update); |
| 466 } else { |
| 467 DCHECK_EQ(event->type(), ui::ET_SCROLL_FLING_START); |
| 468 // Mac generates a stream of events. For the purposes of testing, just |
| 469 // generate one. |
| 470 NSEvent* update = cocoa_test_event_utils::TestScrollEvent( |
| 471 location, window_, -event->x_offset(), -event->y_offset(), true, |
| 472 NSEventPhaseNone, NSEventPhaseChanged); |
| 473 EmulateSendEvent(window_, update); |
| 474 |
| 475 // Never leave the momentum part hanging. |
| 476 NSEvent* end = cocoa_test_event_utils::TestScrollEvent( |
| 477 location, window_, 0, 0, true, NSEventPhaseNone, NSEventPhaseEnded); |
| 478 EmulateSendEvent(window_, end); |
| 479 in_trackpad_scroll = false; |
| 480 } |
| 481 |
| 482 last_scroll_timestamp_ = event->time_stamp(); |
| 483 } |
| 484 |
| 395 void EventGeneratorDelegateMac::SetContext(ui::test::EventGenerator* owner, | 485 void EventGeneratorDelegateMac::SetContext(ui::test::EventGenerator* owner, |
| 396 gfx::NativeWindow root_window, | 486 gfx::NativeWindow root_window, |
| 397 gfx::NativeWindow window) { | 487 gfx::NativeWindow window) { |
| 398 // Mac doesn't use a |root_window|. Assume that if a single-argument | 488 // Mac doesn't use a |root_window|. Assume that if a single-argument |
| 399 // constructor was used, it should be the actual |window|. | 489 // constructor was used, it should be the actual |window|. |
| 400 if (!window) | 490 if (!window) |
| 401 window = root_window; | 491 window = root_window; |
| 402 | 492 |
| 403 swizzle_pressed_.reset(); | 493 swizzle_pressed_.reset(); |
| 404 swizzle_location_.reset(); | 494 swizzle_location_.reset(); |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 504 - (NSEvent*)currentEvent { | 594 - (NSEvent*)currentEvent { |
| 505 if (g_current_event) | 595 if (g_current_event) |
| 506 return g_current_event; | 596 return g_current_event; |
| 507 | 597 |
| 508 // Find the original implementation and invoke it. | 598 // Find the original implementation and invoke it. |
| 509 IMP original = EventGeneratorDelegateMac::GetInstance()->CurrentEventMethod(); | 599 IMP original = EventGeneratorDelegateMac::GetInstance()->CurrentEventMethod(); |
| 510 return original(self, _cmd); | 600 return original(self, _cmd); |
| 511 } | 601 } |
| 512 | 602 |
| 513 @end | 603 @end |
| OLD | NEW |