| 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 |