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

Side by Side Diff: ui/base/test/ui_controls_mac.mm

Issue 809773006: MacViews: Intercept events for Menus (after AppKit has interpreted keystrokes) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@20141205-MacViews-AcceleratedWidget-PLUS-AddingLayers-fromcl-PLUS-bringup
Patch Set: A few more cleanups Created 5 years, 10 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 unified diff | Download patch
« no previous file with comments | « no previous file | ui/events/keycodes/keyboard_code_conversion_mac.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 "ui/base/test/ui_controls.h" 5 #include "ui/base/test/ui_controls.h"
6 6
7 #import <Cocoa/Cocoa.h> 7 #import <Cocoa/Cocoa.h>
8 #include <mach/mach_time.h>
9 #include <vector> 8 #include <vector>
10 9
11 #include "base/bind.h" 10 #include "base/bind.h"
12 #include "base/callback.h" 11 #include "base/callback.h"
13 #include "base/message_loop/message_loop.h" 12 #include "base/message_loop/message_loop.h"
14 #include "ui/events/keycodes/keyboard_code_conversion_mac.h" 13 #include "ui/events/keycodes/keyboard_code_conversion_mac.h"
15 14 #import "ui/events/test/cocoa_test_event_utils.h"
16 15
17 // Implementation details: We use [NSApplication sendEvent:] instead 16 // Implementation details: We use [NSApplication sendEvent:] instead
18 // of [NSApplication postEvent:atStart:] so that the event gets sent 17 // of [NSApplication postEvent:atStart:] so that the event gets sent
19 // immediately. This lets us run the post-event task right 18 // immediately. This lets us run the post-event task right
20 // immediately as well. Unfortunately I cannot subclass NSEvent (it's 19 // immediately as well. Unfortunately I cannot subclass NSEvent (it's
21 // probably a class cluster) to allow other easy answers. For 20 // probably a class cluster) to allow other easy answers. For
22 // 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
23 // dealloc routine (which necessarily happens after the event is 22 // dealloc routine (which necessarily happens after the event is
24 // dispatched). Unlike Linux, Mac does not have message loop 23 // dispatched). Unlike Linux, Mac does not have message loop
25 // observer/notification. Unlike windows, I cannot post non-events 24 // observer/notification. Unlike windows, I cannot post non-events
(...skipping 10 matching lines...) Expand all
36 // processed, we setup a task to watch for the event queue time to time and 35 // processed, we setup a task to watch for the event queue time to time and
37 // notify the caller as soon as there is no event in the queue. 36 // notify the caller as soon as there is no event in the queue.
38 // 37 //
39 // TODO(suzhe): 38 // TODO(suzhe):
40 // 1. Investigate why using [NSApplication postEvent:atStart:] for keyboard 39 // 1. Investigate why using [NSApplication postEvent:atStart:] for keyboard
41 // events causes BrowserKeyEventsTest.CommandKeyEvents to fail. 40 // events causes BrowserKeyEventsTest.CommandKeyEvents to fail.
42 // See http://crbug.com/49270 41 // See http://crbug.com/49270
43 // 2. On OSX 10.6, [NSEvent addLocalMonitorForEventsMatchingMask:handler:] may 42 // 2. On OSX 10.6, [NSEvent addLocalMonitorForEventsMatchingMask:handler:] may
44 // be used, so that we don't need to poll the event queue time to time. 43 // be used, so that we don't need to poll the event queue time to time.
45 44
45 using cocoa_test_event_utils::SynthesizeKeyEvent;
46 using cocoa_test_event_utils::TimeIntervalSinceSystemStartup;
47
46 namespace { 48 namespace {
47 49
48 // Stores the current mouse location on the screen. So that we can use it 50 // Stores the current mouse location on the screen. So that we can use it
49 // when firing keyboard and mouse click events. 51 // when firing keyboard and mouse click events.
50 NSPoint g_mouse_location = { 0, 0 }; 52 NSPoint g_mouse_location = { 0, 0 };
51 53
52 bool g_ui_controls_enabled = false; 54 bool g_ui_controls_enabled = false;
53 55
54 // From
55 // http://stackoverflow.com/questions/1597383/cgeventtimestamp-to-nsdate
56 // Which credits Apple sample code for this routine.
57 uint64_t UpTimeInNanoseconds(void) {
58 uint64_t time;
59 uint64_t timeNano;
60 static mach_timebase_info_data_t sTimebaseInfo;
61
62 time = mach_absolute_time();
63
64 // Convert to nanoseconds.
65
66 // If this is the first time we've run, get the timebase.
67 // We can use denom == 0 to indicate that sTimebaseInfo is
68 // uninitialised because it makes no sense to have a zero
69 // denominator is a fraction.
70 if (sTimebaseInfo.denom == 0) {
71 (void) mach_timebase_info(&sTimebaseInfo);
72 }
73
74 // This could overflow; for testing needs we probably don't care.
75 timeNano = time * sTimebaseInfo.numer / sTimebaseInfo.denom;
76 return timeNano;
77 }
78
79 NSTimeInterval TimeIntervalSinceSystemStartup() {
80 return UpTimeInNanoseconds() / 1000000000.0;
81 }
82
83 // Creates and returns an autoreleased key event.
84 NSEvent* SynthesizeKeyEvent(NSWindow* window,
85 bool keyDown,
86 ui::KeyboardCode keycode,
87 NSUInteger flags) {
88 unichar character;
89 unichar shifted_character;
90 int macKeycode = ui::MacKeyCodeForWindowsKeyCode(
91 keycode, flags, &shifted_character, &character);
92
93 if (macKeycode < 0)
94 return nil;
95
96 // Note that, in line with AppKit's documentation (and tracing "real" events),
97 // -[NSEvent charactersIngoringModifiers]" are "the characters generated by
98 // the receiving key event as if no modifier key (except for Shift)".
99 // So |charactersIgnoringModifiers| uses |shifted_character|.
100 NSString* charactersIgnoringModifiers =
101 [[[NSString alloc] initWithCharacters:&shifted_character
102 length:1] autorelease];
103 NSString* characters;
104 // The following were determined empirically on OSX 10.9.
105 if (flags & NSControlKeyMask) {
106 // If Ctrl is pressed, Cocoa always puts an empty string into |characters|.
107 characters = [NSString string];
108 } else if (flags & NSCommandKeyMask) {
109 // If Cmd is pressed, Cocoa puts a lowercase character into |characters|,
110 // regardless of Shift. If, however, Alt is also pressed then shift *is*
111 // preserved, but re-mappings for Alt are not implemented. Although we still
112 // need to support Alt for things like Alt+Left/Right which don't care.
113 characters =
114 [[[NSString alloc] initWithCharacters:&character length:1] autorelease];
115 } else {
116 // If just Shift or nothing is pressed, |characters| will match
117 // |charactersIgnoringModifiers|. Alt puts a special character into
118 // |characters| (not |charactersIgnoringModifiers|), but they're not mapped
119 // here.
120 characters = charactersIgnoringModifiers;
121 }
122
123 NSEventType type = (keyDown ? NSKeyDown : NSKeyUp);
124
125 // Modifier keys generate NSFlagsChanged event rather than
126 // NSKeyDown/NSKeyUp events.
127 if (keycode == ui::VKEY_CONTROL || keycode == ui::VKEY_SHIFT ||
128 keycode == ui::VKEY_MENU || keycode == ui::VKEY_COMMAND)
129 type = NSFlagsChanged;
130
131 // For events other than mouse moved, [event locationInWindow] is
132 // UNDEFINED if the event is not NSMouseMoved. Thus, the (0,0)
133 // location should be fine.
134 NSEvent* event = [NSEvent keyEventWithType:type
135 location:NSZeroPoint
136 modifierFlags:flags
137 timestamp:TimeIntervalSinceSystemStartup()
138 windowNumber:[window windowNumber]
139 context:nil
140 characters:characters
141 charactersIgnoringModifiers:charactersIgnoringModifiers
142 isARepeat:NO
143 keyCode:(unsigned short)macKeycode];
144
145 return event;
146 }
147
148 // Creates the proper sequence of autoreleased key events for a key down + up. 56 // Creates the proper sequence of autoreleased key events for a key down + up.
149 void SynthesizeKeyEventsSequence(NSWindow* window, 57 void SynthesizeKeyEventsSequence(NSWindow* window,
150 ui::KeyboardCode keycode, 58 ui::KeyboardCode keycode,
151 bool control, 59 bool control,
152 bool shift, 60 bool shift,
153 bool alt, 61 bool alt,
154 bool command, 62 bool command,
155 std::vector<NSEvent*>* events) { 63 std::vector<NSEvent*>* events) {
156 NSEvent* event = nil; 64 NSEvent* event = nil;
157 NSUInteger flags = 0; 65 NSUInteger flags = 0;
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after
426 void RunClosureAfterAllPendingUIEvents(const base::Closure& closure) { 334 void RunClosureAfterAllPendingUIEvents(const base::Closure& closure) {
427 base::MessageLoop::current()->PostTask( 335 base::MessageLoop::current()->PostTask(
428 FROM_HERE, base::Bind(&EventQueueWatcher, closure)); 336 FROM_HERE, base::Bind(&EventQueueWatcher, closure));
429 } 337 }
430 338
431 bool IsFullKeyboardAccessEnabled() { 339 bool IsFullKeyboardAccessEnabled() {
432 return [NSApp isFullKeyboardAccessEnabled]; 340 return [NSApp isFullKeyboardAccessEnabled];
433 } 341 }
434 342
435 } // namespace ui_controls 343 } // namespace ui_controls
OLDNEW
« no previous file with comments | « no previous file | ui/events/keycodes/keyboard_code_conversion_mac.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698