Index: ui/events/cocoa/events_mac_unittest.mm |
diff --git a/ui/events/cocoa/events_mac_unittest.mm b/ui/events/cocoa/events_mac_unittest.mm |
new file mode 100644 |
index 0000000000000000000000000000000000000000..9b930845705bd3de3417bc30c4d339b54a2d5c62 |
--- /dev/null |
+++ b/ui/events/cocoa/events_mac_unittest.mm |
@@ -0,0 +1,243 @@ |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "ui/events/event_utils.h" |
+ |
+#import <Cocoa/Cocoa.h> |
+ |
+#include "base/mac/scoped_cftyperef.h" |
+#include "base/memory/scoped_ptr.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+#include "ui/events/event_constants.h" |
+#import "ui/events/test/cocoa_test_event_utils.h" |
+#include "ui/gfx/point.h" |
+#import "ui/gfx/test/ui_cocoa_test_helper.h" |
+ |
+namespace { |
+ |
+NSWindow* g_test_window = nil; |
+ |
+} // namespace |
+ |
+// Mac APIs for creating test events are frustrating. Quartz APIs have, e.g., |
+// CGEventCreateMouseEvent() which can't set a window or modifier flags. |
+// Cocoa APIs have +[NSEvent mouseEventWithType:..] which can't set |
+// buttonNumber or scroll deltas. To work around this, these tests use some |
+// Objective C magic to donate member functions to NSEvent temporarily. |
+@interface MiddleMouseButtonNumberDonor : NSObject |
+@end |
+ |
+@interface TestWindowDonor : NSObject |
+@end |
+ |
+@implementation MiddleMouseButtonNumberDonor |
+- (NSUInteger)buttonNumber { return 2; } |
+@end |
+ |
+@implementation TestWindowDonor |
+- (NSWindow*)window { return g_test_window; } |
+@end |
+ |
+namespace ui { |
+ |
+namespace { |
+ |
+class EventsMacTest : public CocoaTest { |
+ public: |
+ EventsMacTest() {} |
Robert Sesek
2014/04/25 15:39:23
Don't need if you're not doing work in it.
tapted
2014/04/28 07:39:49
This is to get around "events_mac_unittest.mm:123:
|
+ |
+ gfx::Point Flip(gfx::Point window_location) { |
+ window_location.set_y( |
+ NSHeight([test_window() frame]) - window_location.y()); |
+ return window_location; |
+ } |
+ |
+ void SwizzleMiddleMouseButton() { |
+ DCHECK(!swizzler_); |
+ swizzler_.reset(new ScopedClassSwizzler( |
+ [NSEvent class], |
+ [MiddleMouseButtonNumberDonor class], |
+ @selector(buttonNumber))); |
+ } |
+ |
+ void SwizzleTestWindow() { |
+ DCHECK(!g_test_window); |
+ DCHECK(!swizzler_); |
+ g_test_window = test_window(); |
+ swizzler_.reset(new ScopedClassSwizzler( |
+ [NSEvent class], |
+ [TestWindowDonor class], |
+ @selector(window))); |
+ } |
+ |
+ void ClearSwizzle() { |
+ swizzler_.reset(); |
+ g_test_window = nil; |
+ } |
+ |
+ NSEvent* TestMouseEvent(NSEventType type, |
+ const gfx::Point &window_location, |
+ NSInteger modifier_flags) { |
+ NSPoint point = NSPointFromCGPoint(Flip(window_location).ToCGPoint()); |
+ return [NSEvent mouseEventWithType:type |
+ location:point |
+ modifierFlags:modifier_flags |
+ timestamp:0 |
+ windowNumber:[test_window() windowNumber] |
+ context:nil |
+ eventNumber:0 |
+ clickCount:0 |
+ pressure:1.0]; |
+ } |
+ |
+ NSEvent* TestScrollEvent(const gfx::Point& window_location, |
+ int32_t delta_x, |
+ int32_t delta_y) { |
+ SwizzleTestWindow(); |
+ base::ScopedCFTypeRef<CGEventRef> scroll( |
+ CGEventCreateScrollWheelEvent(NULL, |
+ kCGScrollEventUnitLine, |
+ 2, |
+ delta_y, |
+ delta_x)); |
+ // CGEvents are always in global display coordinates. These are like screen |
+ // coordinates, but flipped. But first the point needs to be converted out |
+ // of window coordinates (which also requires flipping). |
+ NSPoint window_point = |
+ NSPointFromCGPoint(Flip(window_location).ToCGPoint()); |
+ NSPoint screen_point = [test_window() convertBaseToScreen:window_point]; |
+ CGFloat primary_screen_height = |
+ NSHeight([[[NSScreen screens] objectAtIndex:0] frame]); |
+ screen_point.y = primary_screen_height - screen_point.y; |
+ CGEventSetLocation(scroll, NSPointToCGPoint(screen_point)); |
+ return [NSEvent eventWithCGEvent:scroll]; |
+ } |
+ |
+ private: |
+ scoped_ptr<ScopedClassSwizzler> swizzler_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(EventsMacTest); |
+}; |
+ |
+} // namespace |
+ |
+TEST_F(EventsMacTest, EventFlagsFromNative) { |
+ // Left click. |
+ NSEvent* left = cocoa_test_event_utils::MouseEventWithType(NSLeftMouseUp, 0); |
+ EXPECT_EQ(EF_LEFT_MOUSE_BUTTON, EventFlagsFromNative(left)); |
+ |
+ // Right click. |
+ NSEvent* right = cocoa_test_event_utils::MouseEventWithType(NSRightMouseUp, |
+ 0); |
+ EXPECT_EQ(EF_RIGHT_MOUSE_BUTTON, EventFlagsFromNative(right)); |
+ |
+ // Middle click. |
+ NSEvent* middle = cocoa_test_event_utils::MouseEventWithType(NSOtherMouseUp, |
+ 0); |
+ EXPECT_EQ(EF_MIDDLE_MOUSE_BUTTON, EventFlagsFromNative(middle)); |
+ |
+ // Caps + Left |
+ NSEvent* caps = cocoa_test_event_utils::MouseEventWithType( |
+ NSLeftMouseUp, NSAlphaShiftKeyMask); |
+ EXPECT_EQ(EF_LEFT_MOUSE_BUTTON | EF_CAPS_LOCK_DOWN, |
+ EventFlagsFromNative(caps)); |
+ |
+ // Shift + Left |
+ NSEvent* shift = cocoa_test_event_utils::MouseEventWithType(NSLeftMouseUp, |
+ NSShiftKeyMask); |
+ EXPECT_EQ(EF_LEFT_MOUSE_BUTTON | EF_SHIFT_DOWN, EventFlagsFromNative(shift)); |
+ |
+ // Ctrl + Left |
+ NSEvent* ctrl = cocoa_test_event_utils::MouseEventWithType(NSLeftMouseUp, |
+ NSControlKeyMask); |
+ EXPECT_EQ(EF_LEFT_MOUSE_BUTTON | EF_CONTROL_DOWN, EventFlagsFromNative(ctrl)); |
+ |
+ // Alt + Left |
+ NSEvent* alt = cocoa_test_event_utils::MouseEventWithType(NSLeftMouseUp, |
+ NSAlternateKeyMask); |
+ EXPECT_EQ(EF_LEFT_MOUSE_BUTTON | EF_ALT_DOWN, EventFlagsFromNative(alt)); |
+ |
+ // Cmd + Left |
+ NSEvent* cmd = cocoa_test_event_utils::MouseEventWithType(NSLeftMouseUp, |
+ NSCommandKeyMask); |
+ EXPECT_EQ(EF_LEFT_MOUSE_BUTTON | EF_COMMAND_DOWN, EventFlagsFromNative(cmd)); |
+ |
+ // Shift + Ctrl + Left |
+ NSEvent* shiftctrl = cocoa_test_event_utils::MouseEventWithType( |
+ NSLeftMouseUp, NSShiftKeyMask | NSControlKeyMask); |
+ EXPECT_EQ(EF_LEFT_MOUSE_BUTTON | EF_SHIFT_DOWN | EF_CONTROL_DOWN, |
+ EventFlagsFromNative(shiftctrl)); |
+ |
+ // Cmd + Alt + Right |
+ NSEvent* cmdalt = cocoa_test_event_utils::MouseEventWithType( |
+ NSLeftMouseUp, NSCommandKeyMask | NSAlternateKeyMask); |
+ EXPECT_EQ(EF_LEFT_MOUSE_BUTTON | EF_COMMAND_DOWN | EF_ALT_DOWN, |
+ EventFlagsFromNative(cmdalt)); |
+} |
+ |
+// Tests mouse button presses and mouse wheel events. |
+TEST_F(EventsMacTest, ButtonEvents) { |
+ gfx::Point location(5, 10); |
+ gfx::Vector2d offset; |
+ |
+ NSEvent* event = TestMouseEvent(NSLeftMouseDown, location, 0); |
+ EXPECT_EQ(ui::ET_MOUSE_PRESSED, ui::EventTypeFromNative(event)); |
+ EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, ui::EventFlagsFromNative(event)); |
+ EXPECT_EQ(location, ui::EventLocationFromNative(event)); |
+ |
+ SwizzleMiddleMouseButton(); |
+ event = TestMouseEvent(NSOtherMouseDown, location, NSShiftKeyMask); |
+ EXPECT_EQ(ui::ET_MOUSE_PRESSED, ui::EventTypeFromNative(event)); |
+ EXPECT_EQ(ui::EF_MIDDLE_MOUSE_BUTTON | ui::EF_SHIFT_DOWN, |
+ ui::EventFlagsFromNative(event)); |
+ EXPECT_EQ(location, ui::EventLocationFromNative(event)); |
+ ClearSwizzle(); |
+ |
+ event = TestMouseEvent(NSRightMouseUp, location, 0); |
+ EXPECT_EQ(ui::ET_MOUSE_RELEASED, ui::EventTypeFromNative(event)); |
+ EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, ui::EventFlagsFromNative(event)); |
+ EXPECT_EQ(location, ui::EventLocationFromNative(event)); |
+ |
+ // Scroll up. |
+ event = TestScrollEvent(location, 0, 1); |
+ EXPECT_EQ(ui::ET_MOUSEWHEEL, ui::EventTypeFromNative(event)); |
+ EXPECT_EQ(0, ui::EventFlagsFromNative(event)); |
+ EXPECT_EQ(location.ToString(), ui::EventLocationFromNative(event).ToString()); |
+ offset = ui::GetMouseWheelOffset(event); |
+ EXPECT_GT(offset.y(), 0); |
+ EXPECT_EQ(0, offset.x()); |
+ ClearSwizzle(); |
+ |
+ // Scroll down. |
+ event = TestScrollEvent(location, 0, -1); |
+ EXPECT_EQ(ui::ET_MOUSEWHEEL, ui::EventTypeFromNative(event)); |
+ EXPECT_EQ(0, ui::EventFlagsFromNative(event)); |
+ EXPECT_EQ(location, ui::EventLocationFromNative(event)); |
+ offset = ui::GetMouseWheelOffset(event); |
+ EXPECT_LT(offset.y(), 0); |
+ EXPECT_EQ(0, offset.x()); |
+ ClearSwizzle(); |
+ |
+ // Scroll left. |
+ event = TestScrollEvent(location, 1, 0); |
+ EXPECT_EQ(ui::ET_MOUSEWHEEL, ui::EventTypeFromNative(event)); |
+ EXPECT_EQ(0, ui::EventFlagsFromNative(event)); |
+ EXPECT_EQ(location, ui::EventLocationFromNative(event)); |
+ offset = ui::GetMouseWheelOffset(event); |
+ EXPECT_EQ(0, offset.y()); |
+ EXPECT_GT(offset.x(), 0); |
+ ClearSwizzle(); |
+ |
+ // Scroll right. |
+ event = TestScrollEvent(location, -1, 0); |
+ EXPECT_EQ(ui::ET_MOUSEWHEEL, ui::EventTypeFromNative(event)); |
+ EXPECT_EQ(0, ui::EventFlagsFromNative(event)); |
+ EXPECT_EQ(location, ui::EventLocationFromNative(event)); |
+ offset = ui::GetMouseWheelOffset(event); |
+ EXPECT_EQ(0, offset.y()); |
+ EXPECT_LT(offset.x(), 0); |
+ ClearSwizzle(); |
+} |
+ |
+} // namespace ui |