Index: ui/events/test/cocoa_test_event_utils.mm |
diff --git a/ui/events/test/cocoa_test_event_utils.mm b/ui/events/test/cocoa_test_event_utils.mm |
index 2694b84e1d552ef1dd5575a881a08dc11933c303..b27cd12259923336123469f0761ce4899ddd7dac 100644 |
--- a/ui/events/test/cocoa_test_event_utils.mm |
+++ b/ui/events/test/cocoa_test_event_utils.mm |
@@ -3,11 +3,42 @@ |
// found in the LICENSE file. |
#import <Cocoa/Cocoa.h> |
+#include <mach/mach_time.h> |
+#import "ui/events/keycodes/keyboard_code_conversion_mac.h" |
#include "ui/events/test/cocoa_test_event_utils.h" |
namespace cocoa_test_event_utils { |
+namespace { |
+ |
+// From |
+// http://stackoverflow.com/questions/1597383/cgeventtimestamp-to-nsdate |
+// Which credits Apple sample code for this routine. |
+uint64_t UpTimeInNanoseconds(void) { |
+ uint64_t time; |
+ uint64_t timeNano; |
+ static mach_timebase_info_data_t sTimebaseInfo; |
+ |
+ time = mach_absolute_time(); |
+ |
+ // Convert to nanoseconds. |
+ |
+ // If this is the first time we've run, get the timebase. |
+ // We can use denom == 0 to indicate that sTimebaseInfo is |
+ // uninitialised because it makes no sense to have a zero |
+ // denominator is a fraction. |
+ if (sTimebaseInfo.denom == 0) { |
+ (void) mach_timebase_info(&sTimebaseInfo); |
+ } |
+ |
+ // This could overflow; for testing needs we probably don't care. |
+ timeNano = time * sTimebaseInfo.numer / sTimebaseInfo.denom; |
+ return timeNano; |
+} |
+ |
+} // namespace |
+ |
NSEvent* MouseEventAtPoint(NSPoint point, NSEventType type, |
NSUInteger modifiers) { |
if (type == NSOtherMouseUp) { |
@@ -132,4 +163,72 @@ NSEvent* OtherEventWithType(NSEventType event_type) { |
data2:0]; |
} |
+NSTimeInterval TimeIntervalSinceSystemStartup() { |
+ return UpTimeInNanoseconds() / 1000000000.0; |
+} |
+ |
+NSEvent* SynthesizeKeyEvent(NSWindow* window, |
+ bool keyDown, |
+ ui::KeyboardCode keycode, |
+ NSUInteger flags) { |
+ unichar character; |
+ unichar shifted_character; |
+ int macKeycode = ui::MacKeyCodeForWindowsKeyCode( |
+ keycode, flags, &shifted_character, &character); |
+ |
+ if (macKeycode < 0) |
+ return nil; |
+ |
+ // Note that, in line with AppKit's documentation (and tracing "real" events), |
+ // -[NSEvent charactersIngoringModifiers]" are "the characters generated by |
+ // the receiving key event as if no modifier key (except for Shift)". |
+ // So |charactersIgnoringModifiers| uses |shifted_character|. |
+ NSString* charactersIgnoringModifiers = |
+ [[[NSString alloc] initWithCharacters:&shifted_character |
+ length:1] autorelease]; |
+ NSString* characters; |
+ // The following were determined empirically on OSX 10.9. |
+ if (flags & NSControlKeyMask) { |
+ // If Ctrl is pressed, Cocoa always puts an empty string into |characters|. |
+ characters = [NSString string]; |
+ } else if (flags & NSCommandKeyMask) { |
+ // If Cmd is pressed, Cocoa puts a lowercase character into |characters|, |
+ // regardless of Shift. If, however, Alt is also pressed then shift *is* |
+ // preserved, but re-mappings for Alt are not implemented. Although we still |
+ // need to support Alt for things like Alt+Left/Right which don't care. |
+ characters = |
+ [[[NSString alloc] initWithCharacters:&character length:1] autorelease]; |
+ } else { |
+ // If just Shift or nothing is pressed, |characters| will match |
+ // |charactersIgnoringModifiers|. Alt puts a special character into |
+ // |characters| (not |charactersIgnoringModifiers|), but they're not mapped |
+ // here. |
+ characters = charactersIgnoringModifiers; |
+ } |
+ |
+ NSEventType type = (keyDown ? NSKeyDown : NSKeyUp); |
+ |
+ // Modifier keys generate NSFlagsChanged event rather than |
+ // NSKeyDown/NSKeyUp events. |
+ if (keycode == ui::VKEY_CONTROL || keycode == ui::VKEY_SHIFT || |
+ keycode == ui::VKEY_MENU || keycode == ui::VKEY_COMMAND) |
+ type = NSFlagsChanged; |
+ |
+ // For events other than mouse moved, [event locationInWindow] is |
+ // UNDEFINED if the event is not NSMouseMoved. Thus, the (0,0) |
+ // location should be fine. |
+ NSEvent* event = [NSEvent keyEventWithType:type |
+ location:NSZeroPoint |
+ modifierFlags:flags |
+ timestamp:TimeIntervalSinceSystemStartup() |
+ windowNumber:[window windowNumber] |
+ context:nil |
+ characters:characters |
+ charactersIgnoringModifiers:charactersIgnoringModifiers |
+ isARepeat:NO |
+ keyCode:(unsigned short)macKeycode]; |
+ |
+ return event; |
+} |
+ |
} // namespace cocoa_test_event_utils |