Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(133)

Unified Diff: ui/events/cocoa/events_mac_unittest.mm

Issue 251493002: MacViews: Implement basic NSEvent -> ui::Event conversion for Mac (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: selfnit Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: ui/events/cocoa/events_mac_unittest.mm
diff --git a/ui/events/cocoa/cocoa_event_utils_unittest.mm b/ui/events/cocoa/events_mac_unittest.mm
similarity index 32%
rename from ui/events/cocoa/cocoa_event_utils_unittest.mm
rename to ui/events/cocoa/events_mac_unittest.mm
index 4e24fd2c775ba9b9b2fbaf608b4e68fca90f3ab0..9b930845705bd3de3417bc30c4d339b54a2d5c62 100644
--- a/ui/events/cocoa/cocoa_event_utils_unittest.mm
+++ b/ui/events/cocoa/events_mac_unittest.mm
@@ -2,25 +2,127 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "ui/events/cocoa/cocoa_event_utils.h"
+#include "ui/events/event_utils.h"
-#import <objc/objc-class.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 "testing/platform_test.h"
#include "ui/events/event_constants.h"
-#include "ui/events/event_utils.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 CocoaEventUtilsTest : public CocoaTest {
+class EventsMacTest : public CocoaTest {
+ public:
+ EventsMacTest() {}
+
+ 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);
};
-TEST_F(CocoaEventUtilsTest, EventFlagsFromNative) {
+} // namespace
+
+TEST_F(EventsMacTest, EventFlagsFromNative) {
// Left click.
NSEvent* left = cocoa_test_event_utils::MouseEventWithType(NSLeftMouseUp, 0);
EXPECT_EQ(EF_LEFT_MOUSE_BUTTON, EventFlagsFromNative(left));
@@ -74,6 +176,68 @@ TEST_F(CocoaEventUtilsTest, EventFlagsFromNative) {
EventFlagsFromNative(cmdalt));
}
-} // namespace
+// 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

Powered by Google App Engine
This is Rietveld 408576698