OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 #include "chrome/browser/automation/ui_controls.h" | 5 #include "chrome/browser/automation/ui_controls.h" |
6 | 6 |
7 #import <Cocoa/Cocoa.h> | 7 #import <Cocoa/Cocoa.h> |
8 #include <mach/mach_time.h> | 8 #include <mach/mach_time.h> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
11 #include "app/keyboard_code_conversion_mac.h" | 11 #include "base/keyboard_code_conversion_mac.h" |
12 #include "base/message_loop.h" | 12 #include "base/message_loop.h" |
13 #include "chrome/browser/automation/ui_controls_internal.h" | 13 #include "chrome/browser/automation/ui_controls_internal.h" |
14 #include "chrome/browser/chrome_thread.h" | 14 #include "chrome/browser/chrome_thread.h" |
15 | 15 |
16 // Implementation details: We use [NSApplication sendEvent:] instead | 16 // Implementation details: We use [NSApplication sendEvent:] instead |
17 // of [NSApplication postEvent:atStart:] so that the event gets sent | 17 // of [NSApplication postEvent:atStart:] so that the event gets sent |
18 // immediately. This lets us run the post-event task right | 18 // immediately. This lets us run the post-event task right |
19 // immediately as well. Unfortunately I cannot subclass NSEvent (it's | 19 // immediately as well. Unfortunately I cannot subclass NSEvent (it's |
20 // probably a class cluster) to allow other easy answers. For | 20 // probably a class cluster) to allow other easy answers. For |
21 // example, if I could subclass NSEvent, I could run the Task in it's | 21 // example, if I could subclass NSEvent, I could run the Task in it's |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
69 return timeNano; | 69 return timeNano; |
70 } | 70 } |
71 | 71 |
72 NSTimeInterval TimeIntervalSinceSystemStartup() { | 72 NSTimeInterval TimeIntervalSinceSystemStartup() { |
73 return UpTimeInNanoseconds() / 1000000000.0; | 73 return UpTimeInNanoseconds() / 1000000000.0; |
74 } | 74 } |
75 | 75 |
76 // Creates and returns an autoreleased key event. | 76 // Creates and returns an autoreleased key event. |
77 NSEvent* SynthesizeKeyEvent(NSWindow* window, | 77 NSEvent* SynthesizeKeyEvent(NSWindow* window, |
78 bool keyDown, | 78 bool keyDown, |
79 app::KeyboardCode keycode, | 79 base::KeyboardCode keycode, |
80 NSUInteger flags) { | 80 NSUInteger flags) { |
81 unichar character; | 81 unichar character; |
82 unichar characterIgnoringModifiers; | 82 unichar characterIgnoringModifiers; |
83 int macKeycode = app::MacKeyCodeForWindowsKeyCode( | 83 int macKeycode = base::MacKeyCodeForWindowsKeyCode( |
84 keycode, flags, &character, &characterIgnoringModifiers); | 84 keycode, flags, &character, &characterIgnoringModifiers); |
85 | 85 |
86 if (macKeycode < 0) | 86 if (macKeycode < 0) |
87 return nil; | 87 return nil; |
88 | 88 |
89 NSString* charactersIgnoringModifiers = | 89 NSString* charactersIgnoringModifiers = |
90 [[[NSString alloc] initWithCharacters:&characterIgnoringModifiers | 90 [[[NSString alloc] initWithCharacters:&characterIgnoringModifiers |
91 length:1] | 91 length:1] |
92 autorelease]; | 92 autorelease]; |
93 NSString* characters = | 93 NSString* characters = |
94 [[[NSString alloc] initWithCharacters:&character length:1] autorelease]; | 94 [[[NSString alloc] initWithCharacters:&character length:1] autorelease]; |
95 | 95 |
96 NSEventType type = (keyDown ? NSKeyDown : NSKeyUp); | 96 NSEventType type = (keyDown ? NSKeyDown : NSKeyUp); |
97 | 97 |
98 // Modifier keys generate NSFlagsChanged event rather than | 98 // Modifier keys generate NSFlagsChanged event rather than |
99 // NSKeyDown/NSKeyUp events. | 99 // NSKeyDown/NSKeyUp events. |
100 if (keycode == app::VKEY_CONTROL || keycode == app::VKEY_SHIFT || | 100 if (keycode == base::VKEY_CONTROL || keycode == base::VKEY_SHIFT || |
101 keycode == app::VKEY_MENU || keycode == app::VKEY_COMMAND) | 101 keycode == base::VKEY_MENU || keycode == base::VKEY_COMMAND) |
102 type = NSFlagsChanged; | 102 type = NSFlagsChanged; |
103 | 103 |
104 // For events other than mouse moved, [event locationInWindow] is | 104 // For events other than mouse moved, [event locationInWindow] is |
105 // UNDEFINED if the event is not NSMouseMoved. Thus, the (0,0) | 105 // UNDEFINED if the event is not NSMouseMoved. Thus, the (0,0) |
106 // location should be fine. | 106 // location should be fine. |
107 NSEvent* event = | 107 NSEvent* event = |
108 [NSEvent keyEventWithType:type | 108 [NSEvent keyEventWithType:type |
109 location:NSMakePoint(0, 0) | 109 location:NSMakePoint(0, 0) |
110 modifierFlags:flags | 110 modifierFlags:flags |
111 timestamp:TimeIntervalSinceSystemStartup() | 111 timestamp:TimeIntervalSinceSystemStartup() |
112 windowNumber:[window windowNumber] | 112 windowNumber:[window windowNumber] |
113 context:nil | 113 context:nil |
114 characters:characters | 114 characters:characters |
115 charactersIgnoringModifiers:charactersIgnoringModifiers | 115 charactersIgnoringModifiers:charactersIgnoringModifiers |
116 isARepeat:NO | 116 isARepeat:NO |
117 keyCode:(unsigned short)macKeycode]; | 117 keyCode:(unsigned short)macKeycode]; |
118 | 118 |
119 return event; | 119 return event; |
120 } | 120 } |
121 | 121 |
122 // Creates the proper sequence of autoreleased key events for a key down + up. | 122 // Creates the proper sequence of autoreleased key events for a key down + up. |
123 void SynthesizeKeyEventsSequence(NSWindow* window, | 123 void SynthesizeKeyEventsSequence(NSWindow* window, |
124 app::KeyboardCode keycode, | 124 base::KeyboardCode keycode, |
125 bool control, | 125 bool control, |
126 bool shift, | 126 bool shift, |
127 bool alt, | 127 bool alt, |
128 bool command, | 128 bool command, |
129 std::vector<NSEvent*>* events) { | 129 std::vector<NSEvent*>* events) { |
130 NSEvent* event = nil; | 130 NSEvent* event = nil; |
131 NSUInteger flags = 0; | 131 NSUInteger flags = 0; |
132 if (control) { | 132 if (control) { |
133 flags |= NSControlKeyMask; | 133 flags |= NSControlKeyMask; |
134 event = SynthesizeKeyEvent(window, true, app::VKEY_CONTROL, flags); | 134 event = SynthesizeKeyEvent(window, true, base::VKEY_CONTROL, flags); |
135 DCHECK(event); | 135 DCHECK(event); |
136 events->push_back(event); | 136 events->push_back(event); |
137 } | 137 } |
138 if (shift) { | 138 if (shift) { |
139 flags |= NSShiftKeyMask; | 139 flags |= NSShiftKeyMask; |
140 event = SynthesizeKeyEvent(window, true, app::VKEY_SHIFT, flags); | 140 event = SynthesizeKeyEvent(window, true, base::VKEY_SHIFT, flags); |
141 DCHECK(event); | 141 DCHECK(event); |
142 events->push_back(event); | 142 events->push_back(event); |
143 } | 143 } |
144 if (alt) { | 144 if (alt) { |
145 flags |= NSAlternateKeyMask; | 145 flags |= NSAlternateKeyMask; |
146 event = SynthesizeKeyEvent(window, true, app::VKEY_MENU, flags); | 146 event = SynthesizeKeyEvent(window, true, base::VKEY_MENU, flags); |
147 DCHECK(event); | 147 DCHECK(event); |
148 events->push_back(event); | 148 events->push_back(event); |
149 } | 149 } |
150 if (command) { | 150 if (command) { |
151 flags |= NSCommandKeyMask; | 151 flags |= NSCommandKeyMask; |
152 event = SynthesizeKeyEvent(window, true, app::VKEY_COMMAND, flags); | 152 event = SynthesizeKeyEvent(window, true, base::VKEY_COMMAND, flags); |
153 DCHECK(event); | 153 DCHECK(event); |
154 events->push_back(event); | 154 events->push_back(event); |
155 } | 155 } |
156 | 156 |
157 event = SynthesizeKeyEvent(window, true, keycode, flags); | 157 event = SynthesizeKeyEvent(window, true, keycode, flags); |
158 DCHECK(event); | 158 DCHECK(event); |
159 events->push_back(event); | 159 events->push_back(event); |
160 event = SynthesizeKeyEvent(window, false, keycode, flags); | 160 event = SynthesizeKeyEvent(window, false, keycode, flags); |
161 DCHECK(event); | 161 DCHECK(event); |
162 events->push_back(event); | 162 events->push_back(event); |
163 | 163 |
164 if (command) { | 164 if (command) { |
165 flags &= ~NSCommandKeyMask; | 165 flags &= ~NSCommandKeyMask; |
166 event = SynthesizeKeyEvent(window, false, app::VKEY_COMMAND, flags); | 166 event = SynthesizeKeyEvent(window, false, base::VKEY_COMMAND, flags); |
167 DCHECK(event); | 167 DCHECK(event); |
168 events->push_back(event); | 168 events->push_back(event); |
169 } | 169 } |
170 if (alt) { | 170 if (alt) { |
171 flags &= ~NSAlternateKeyMask; | 171 flags &= ~NSAlternateKeyMask; |
172 event = SynthesizeKeyEvent(window, false, app::VKEY_MENU, flags); | 172 event = SynthesizeKeyEvent(window, false, base::VKEY_MENU, flags); |
173 DCHECK(event); | 173 DCHECK(event); |
174 events->push_back(event); | 174 events->push_back(event); |
175 } | 175 } |
176 if (shift) { | 176 if (shift) { |
177 flags &= ~NSShiftKeyMask; | 177 flags &= ~NSShiftKeyMask; |
178 event = SynthesizeKeyEvent(window, false, app::VKEY_SHIFT, flags); | 178 event = SynthesizeKeyEvent(window, false, base::VKEY_SHIFT, flags); |
179 DCHECK(event); | 179 DCHECK(event); |
180 events->push_back(event); | 180 events->push_back(event); |
181 } | 181 } |
182 if (control) { | 182 if (control) { |
183 flags &= ~NSControlKeyMask; | 183 flags &= ~NSControlKeyMask; |
184 event = SynthesizeKeyEvent(window, false, app::VKEY_CONTROL, flags); | 184 event = SynthesizeKeyEvent(window, false, base::VKEY_CONTROL, flags); |
185 DCHECK(event); | 185 DCHECK(event); |
186 events->push_back(event); | 186 events->push_back(event); |
187 } | 187 } |
188 } | 188 } |
189 | 189 |
190 // A task class to watch for the event queue. The specific task will be fired | 190 // A task class to watch for the event queue. The specific task will be fired |
191 // when there is no more event in the queue. | 191 // when there is no more event in the queue. |
192 class EventQueueWatcher : public Task { | 192 class EventQueueWatcher : public Task { |
193 public: | 193 public: |
194 EventQueueWatcher(Task* task) : task_(task) {} | 194 EventQueueWatcher(Task* task) : task_(task) {} |
(...skipping 19 matching lines...) Expand all Loading... |
214 // Stores the current mouse location on the screen. So that we can use it | 214 // Stores the current mouse location on the screen. So that we can use it |
215 // when firing keyboard and mouse click events. | 215 // when firing keyboard and mouse click events. |
216 NSPoint g_mouse_location = { 0, 0 }; | 216 NSPoint g_mouse_location = { 0, 0 }; |
217 | 217 |
218 } // anonymous namespace | 218 } // anonymous namespace |
219 | 219 |
220 | 220 |
221 namespace ui_controls { | 221 namespace ui_controls { |
222 | 222 |
223 bool SendKeyPress(gfx::NativeWindow window, | 223 bool SendKeyPress(gfx::NativeWindow window, |
224 app::KeyboardCode key, | 224 base::KeyboardCode key, |
225 bool control, | 225 bool control, |
226 bool shift, | 226 bool shift, |
227 bool alt, | 227 bool alt, |
228 bool command) { | 228 bool command) { |
229 return SendKeyPressNotifyWhenDone(window, key, | 229 return SendKeyPressNotifyWhenDone(window, key, |
230 control, shift, alt, command, | 230 control, shift, alt, command, |
231 NULL); | 231 NULL); |
232 } | 232 } |
233 | 233 |
234 // Win and Linux implement a SendKeyPress() this as a | 234 // Win and Linux implement a SendKeyPress() this as a |
235 // SendKeyPressAndRelease(), so we should as well (despite the name). | 235 // SendKeyPressAndRelease(), so we should as well (despite the name). |
236 bool SendKeyPressNotifyWhenDone(gfx::NativeWindow window, | 236 bool SendKeyPressNotifyWhenDone(gfx::NativeWindow window, |
237 app::KeyboardCode key, | 237 base::KeyboardCode key, |
238 bool control, | 238 bool control, |
239 bool shift, | 239 bool shift, |
240 bool alt, | 240 bool alt, |
241 bool command, | 241 bool command, |
242 Task* task) { | 242 Task* task) { |
243 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); | 243 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
244 | 244 |
245 std::vector<NSEvent*> events; | 245 std::vector<NSEvent*> events; |
246 SynthesizeKeyEventsSequence( | 246 SynthesizeKeyEventsSequence( |
247 window, key, control, shift, alt, command, &events); | 247 window, key, control, shift, alt, command, &events); |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
373 NSPoint center = NSMakePoint(NSMidX(bounds), NSMidY(bounds)); | 373 NSPoint center = NSMakePoint(NSMidX(bounds), NSMidY(bounds)); |
374 center = [view convertPoint:center toView:nil]; | 374 center = [view convertPoint:center toView:nil]; |
375 center = [window convertBaseToScreen:center]; | 375 center = [window convertBaseToScreen:center]; |
376 center = NSMakePoint(center.x, [screen frame].size.height - center.y); | 376 center = NSMakePoint(center.x, [screen frame].size.height - center.y); |
377 | 377 |
378 SendMouseMoveNotifyWhenDone(center.x, center.y, | 378 SendMouseMoveNotifyWhenDone(center.x, center.y, |
379 new ClickTask(button, state, task)); | 379 new ClickTask(button, state, task)); |
380 } | 380 } |
381 | 381 |
382 } // ui_controls | 382 } // ui_controls |
OLD | NEW |