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 <mach/mach_time.h> |
6 | 7 |
| 8 #import "ui/events/keycodes/keyboard_code_conversion_mac.h" |
7 #include "ui/events/test/cocoa_test_event_utils.h" | 9 #include "ui/events/test/cocoa_test_event_utils.h" |
8 | 10 |
9 namespace cocoa_test_event_utils { | 11 namespace cocoa_test_event_utils { |
10 | 12 |
| 13 namespace { |
| 14 |
| 15 // From |
| 16 // http://stackoverflow.com/questions/1597383/cgeventtimestamp-to-nsdate |
| 17 // Which credits Apple sample code for this routine. |
| 18 uint64_t UpTimeInNanoseconds(void) { |
| 19 uint64_t time; |
| 20 uint64_t timeNano; |
| 21 static mach_timebase_info_data_t sTimebaseInfo; |
| 22 |
| 23 time = mach_absolute_time(); |
| 24 |
| 25 // Convert to nanoseconds. |
| 26 |
| 27 // If this is the first time we've run, get the timebase. |
| 28 // We can use denom == 0 to indicate that sTimebaseInfo is |
| 29 // uninitialised because it makes no sense to have a zero |
| 30 // denominator is a fraction. |
| 31 if (sTimebaseInfo.denom == 0) { |
| 32 (void) mach_timebase_info(&sTimebaseInfo); |
| 33 } |
| 34 |
| 35 // This could overflow; for testing needs we probably don't care. |
| 36 timeNano = time * sTimebaseInfo.numer / sTimebaseInfo.denom; |
| 37 return timeNano; |
| 38 } |
| 39 |
| 40 } // namespace |
| 41 |
11 NSEvent* MouseEventAtPoint(NSPoint point, NSEventType type, | 42 NSEvent* MouseEventAtPoint(NSPoint point, NSEventType type, |
12 NSUInteger modifiers) { | 43 NSUInteger modifiers) { |
13 if (type == NSOtherMouseUp) { | 44 if (type == NSOtherMouseUp) { |
14 // To synthesize middle clicks we need to create a CGEvent with the | 45 // To synthesize middle clicks we need to create a CGEvent with the |
15 // "center" button flags so that our resulting NSEvent will have the | 46 // "center" button flags so that our resulting NSEvent will have the |
16 // appropriate buttonNumber field. NSEvent provides no way to create a | 47 // appropriate buttonNumber field. NSEvent provides no way to create a |
17 // mouse event with a buttonNumber directly. | 48 // mouse event with a buttonNumber directly. |
18 CGPoint location = { point.x, point.y }; | 49 CGPoint location = { point.x, point.y }; |
19 CGEventRef cg_event = CGEventCreateMouseEvent(NULL, kCGEventOtherMouseUp, | 50 CGEventRef cg_event = CGEventCreateMouseEvent(NULL, kCGEventOtherMouseUp, |
20 location, | 51 location, |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
125 location:NSZeroPoint | 156 location:NSZeroPoint |
126 modifierFlags:0 | 157 modifierFlags:0 |
127 timestamp:0 | 158 timestamp:0 |
128 windowNumber:0 | 159 windowNumber:0 |
129 context:nil | 160 context:nil |
130 subtype:0 | 161 subtype:0 |
131 data1:0 | 162 data1:0 |
132 data2:0]; | 163 data2:0]; |
133 } | 164 } |
134 | 165 |
| 166 NSTimeInterval TimeIntervalSinceSystemStartup() { |
| 167 return UpTimeInNanoseconds() / 1000000000.0; |
| 168 } |
| 169 |
| 170 NSEvent* SynthesizeKeyEvent(NSWindow* window, |
| 171 bool keyDown, |
| 172 ui::KeyboardCode keycode, |
| 173 NSUInteger flags) { |
| 174 unichar character; |
| 175 unichar shifted_character; |
| 176 int macKeycode = ui::MacKeyCodeForWindowsKeyCode( |
| 177 keycode, flags, &shifted_character, &character); |
| 178 |
| 179 if (macKeycode < 0) |
| 180 return nil; |
| 181 |
| 182 // Note that, in line with AppKit's documentation (and tracing "real" events), |
| 183 // -[NSEvent charactersIngoringModifiers]" are "the characters generated by |
| 184 // the receiving key event as if no modifier key (except for Shift)". |
| 185 // So |charactersIgnoringModifiers| uses |shifted_character|. |
| 186 NSString* charactersIgnoringModifiers = |
| 187 [[[NSString alloc] initWithCharacters:&shifted_character |
| 188 length:1] autorelease]; |
| 189 NSString* characters; |
| 190 // The following were determined empirically on OSX 10.9. |
| 191 if (flags & NSControlKeyMask) { |
| 192 // If Ctrl is pressed, Cocoa always puts an empty string into |characters|. |
| 193 characters = [NSString string]; |
| 194 } else if (flags & NSCommandKeyMask) { |
| 195 // If Cmd is pressed, Cocoa puts a lowercase character into |characters|, |
| 196 // regardless of Shift. If, however, Alt is also pressed then shift *is* |
| 197 // preserved, but re-mappings for Alt are not implemented. Although we still |
| 198 // need to support Alt for things like Alt+Left/Right which don't care. |
| 199 characters = |
| 200 [[[NSString alloc] initWithCharacters:&character length:1] autorelease]; |
| 201 } else { |
| 202 // If just Shift or nothing is pressed, |characters| will match |
| 203 // |charactersIgnoringModifiers|. Alt puts a special character into |
| 204 // |characters| (not |charactersIgnoringModifiers|), but they're not mapped |
| 205 // here. |
| 206 characters = charactersIgnoringModifiers; |
| 207 } |
| 208 |
| 209 NSEventType type = (keyDown ? NSKeyDown : NSKeyUp); |
| 210 |
| 211 // Modifier keys generate NSFlagsChanged event rather than |
| 212 // NSKeyDown/NSKeyUp events. |
| 213 if (keycode == ui::VKEY_CONTROL || keycode == ui::VKEY_SHIFT || |
| 214 keycode == ui::VKEY_MENU || keycode == ui::VKEY_COMMAND) |
| 215 type = NSFlagsChanged; |
| 216 |
| 217 // For events other than mouse moved, [event locationInWindow] is |
| 218 // UNDEFINED if the event is not NSMouseMoved. Thus, the (0,0) |
| 219 // location should be fine. |
| 220 NSEvent* event = [NSEvent keyEventWithType:type |
| 221 location:NSZeroPoint |
| 222 modifierFlags:flags |
| 223 timestamp:TimeIntervalSinceSystemStartup() |
| 224 windowNumber:[window windowNumber] |
| 225 context:nil |
| 226 characters:characters |
| 227 charactersIgnoringModifiers:charactersIgnoringModifiers |
| 228 isARepeat:NO |
| 229 keyCode:(unsigned short)macKeycode]; |
| 230 |
| 231 return event; |
| 232 } |
| 233 |
135 } // namespace cocoa_test_event_utils | 234 } // namespace cocoa_test_event_utils |
OLD | NEW |