Chromium Code Reviews| Index: ui/base/test/ui_controls_mac.mm |
| diff --git a/ui/base/test/ui_controls_mac.mm b/ui/base/test/ui_controls_mac.mm |
| index b7615b6c2fd78eab1ddbb87a351cf33f47c4efd1..1aba1b115c13b06d6fc269ec9b1b2a56f4753fe3 100644 |
| --- a/ui/base/test/ui_controls_mac.mm |
| +++ b/ui/base/test/ui_controls_mac.mm |
| @@ -9,10 +9,14 @@ |
| #include "base/bind.h" |
| #include "base/callback.h" |
| +#import "base/mac/foundation_util.h" |
| +#import "base/mac/scoped_objc_class_swizzler.h" |
| #include "base/message_loop/message_loop.h" |
| #include "ui/base/cocoa/cocoa_base_utils.h" |
| #include "ui/events/keycodes/keyboard_code_conversion_mac.h" |
| #import "ui/events/test/cocoa_test_event_utils.h" |
| +#include "ui/gfx/geometry/point.h" |
| +#import "ui/gfx/mac/coordinate_conversion.h" |
| // Implementation details: We use [NSApplication sendEvent:] instead |
| // of [NSApplication postEvent:atStart:] so that the event gets sent |
| @@ -52,6 +56,10 @@ namespace { |
| // when firing keyboard and mouse click events. |
| NSPoint g_mouse_location = { 0, 0 }; |
| +// Stores the current pressed mouse buttons. Indexed by |
| +// ui_controls::MouseButton. |
| +bool g_mouse_button_down[3] = {false, false, false}; |
| + |
| bool g_ui_controls_enabled = false; |
| // Creates the proper sequence of autoreleased key events for a key down + up. |
| @@ -173,10 +181,67 @@ NSWindow* WindowAtCurrentMouseLocation() { |
| } // namespace |
| +// Donates testing implementations of NSEvent methods. |
| +@interface FakeNSEventTestingDonor : NSObject |
| +@end |
| + |
| +@implementation FakeNSEventTestingDonor |
| ++ (NSPoint)mouseLocation { |
| + return g_mouse_location; |
| +} |
| + |
| ++ (NSUInteger)pressedMouseButtons { |
| + NSUInteger result = 0; |
| + const int buttons[3] = { |
| + ui_controls::LEFT, ui_controls::RIGHT, ui_controls::MIDDLE}; |
| + for (size_t i = 0; i < arraysize(buttons); ++i) { |
| + if (g_mouse_button_down[buttons[i]]) |
| + result |= (1 << i); |
| + } |
| + return result; |
| +} |
| +@end |
| + |
| +namespace { |
| + |
| +// Swizzles several Cocoa functions that are used to directly get mouse state, |
| +// so that they will return the current simulated mouse position and pressed |
| +// mouse buttons. |
| +class MockNSEventClassMethods { |
| + public: |
| + static void Init() { |
| + static MockNSEventClassMethods* swizzler = nullptr; |
| + if (!swizzler) { |
| + swizzler = new MockNSEventClassMethods(); |
| + } |
| + } |
| + |
| + protected: |
|
tapted
2016/06/07 00:49:14
nit: private: (and remove private: below)
themblsha
2016/06/07 12:11:11
Done.
|
| + MockNSEventClassMethods() |
| + : mouse_location_swizzler_(new base::mac::ScopedObjCClassSwizzler( |
| + [NSEvent class], |
| + [FakeNSEventTestingDonor class], |
| + @selector(mouseLocation))), |
| + pressed_mouse_buttons_swizzler_(new base::mac::ScopedObjCClassSwizzler( |
| + [NSEvent class], |
| + [FakeNSEventTestingDonor class], |
| + @selector(pressedMouseButtons))) {} |
| + |
| + private: |
| + std::unique_ptr<base::mac::ScopedObjCClassSwizzler> mouse_location_swizzler_; |
|
tapted
2016/06/07 00:49:14
Ah, sorry - these should be regular members, not u
themblsha
2016/06/07 12:11:11
Done.
|
| + std::unique_ptr<base::mac::ScopedObjCClassSwizzler> |
| + pressed_mouse_buttons_swizzler_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(MockNSEventClassMethods); |
| +}; |
| + |
| +} // namespace |
| + |
| namespace ui_controls { |
| void EnableUIControls() { |
| g_ui_controls_enabled = true; |
| + MockNSEventClassMethods::Init(); |
| } |
| bool IsUIControlsEnabled() { |
| @@ -239,9 +304,7 @@ bool SendMouseMove(long x, long y) { |
| // platforms. E.g. (0,0) is upper-left. |
| bool SendMouseMoveNotifyWhenDone(long x, long y, const base::Closure& task) { |
| CHECK(g_ui_controls_enabled); |
| - CGFloat screenHeight = |
| - [[[NSScreen screens] firstObject] frame].size.height; |
| - g_mouse_location = NSMakePoint(x, screenHeight - y); // flip! |
| + g_mouse_location = gfx::ScreenPointToNSPoint(gfx::Point(x, y)); // flip! |
| NSWindow* window = WindowAtCurrentMouseLocation(); |
| @@ -250,16 +313,25 @@ bool SendMouseMoveNotifyWhenDone(long x, long y, const base::Closure& task) { |
| pointInWindow = ui::ConvertPointFromScreenToWindow(window, pointInWindow); |
| NSTimeInterval timestamp = TimeIntervalSinceSystemStartup(); |
| + NSEventType event_type = NSMouseMoved; |
| + if (g_mouse_button_down[LEFT]) { |
| + event_type = NSLeftMouseDragged; |
| + } else if (g_mouse_button_down[RIGHT]) { |
| + event_type = NSRightMouseDragged; |
| + } else if (g_mouse_button_down[MIDDLE]) { |
| + event_type = NSOtherMouseDragged; |
| + } |
| + |
| NSEvent* event = |
| - [NSEvent mouseEventWithType:NSMouseMoved |
| + [NSEvent mouseEventWithType:event_type |
| location:pointInWindow |
| modifierFlags:0 |
| timestamp:timestamp |
| windowNumber:[window windowNumber] |
| context:nil |
| eventNumber:0 |
| - clickCount:0 |
| - pressure:0.0]; |
| + clickCount:event_type == NSMouseMoved ? 0 : 1 |
| + pressure:event_type == NSMouseMoved ? 0.0 : 1.0]; |
| [[NSApplication sharedApplication] postEvent:event atStart:NO]; |
| if (!task.is_null()) { |
| @@ -284,35 +356,38 @@ bool SendMouseEventsNotifyWhenDone(MouseButton type, int state, |
| return (SendMouseEventsNotifyWhenDone(type, DOWN, base::Closure()) && |
| SendMouseEventsNotifyWhenDone(type, UP, task)); |
| } |
| - NSEventType etype = NSLeftMouseDown; |
| + NSEventType event_type = NSLeftMouseDown; |
| if (type == LEFT) { |
| if (state == UP) { |
| - etype = NSLeftMouseUp; |
| + event_type = NSLeftMouseUp; |
| } else { |
| - etype = NSLeftMouseDown; |
| + event_type = NSLeftMouseDown; |
| } |
| } else if (type == MIDDLE) { |
| if (state == UP) { |
| - etype = NSOtherMouseUp; |
| + event_type = NSOtherMouseUp; |
| } else { |
| - etype = NSOtherMouseDown; |
| + event_type = NSOtherMouseDown; |
| } |
| } else if (type == RIGHT) { |
| if (state == UP) { |
| - etype = NSRightMouseUp; |
| + event_type = NSRightMouseUp; |
| } else { |
| - etype = NSRightMouseDown; |
| + event_type = NSRightMouseDown; |
| } |
| } else { |
| + NOTREACHED(); |
| return false; |
| } |
| + g_mouse_button_down[type] = state == DOWN; |
| + |
| NSWindow* window = WindowAtCurrentMouseLocation(); |
| NSPoint pointInWindow = g_mouse_location; |
| if (window) |
| pointInWindow = ui::ConvertPointFromScreenToWindow(window, pointInWindow); |
| NSEvent* event = |
| - [NSEvent mouseEventWithType:etype |
| + [NSEvent mouseEventWithType:event_type |
| location:pointInWindow |
| modifierFlags:0 |
| timestamp:TimeIntervalSinceSystemStartup() |
| @@ -320,7 +395,7 @@ bool SendMouseEventsNotifyWhenDone(MouseButton type, int state, |
| context:nil |
| eventNumber:0 |
| clickCount:1 |
| - pressure:(state == DOWN ? 1.0 : 0.0 )]; |
| + pressure:state == DOWN ? 1.0 : 0.0]; |
| [[NSApplication sharedApplication] postEvent:event atStart:NO]; |
| if (!task.is_null()) { |