OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved. | 2 * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved. |
3 * Copyright (C) 2006-2009 Google Inc. | 3 * Copyright (C) 2006-2009 Google Inc. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
7 * are met: | 7 * are met: |
8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
11 * notice, this list of conditions and the following disclaimer in the | 11 * notice, this list of conditions and the following disclaimer in the |
12 * documentation and/or other materials provided with the distribution. | 12 * documentation and/or other materials provided with the distribution. |
13 * | 13 * |
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY | 14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY |
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR | 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR |
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
25 */ | 25 */ |
26 | 26 |
| 27 #include <ApplicationServices/ApplicationServices.h> |
27 #import <Cocoa/Cocoa.h> | 28 #import <Cocoa/Cocoa.h> |
28 | 29 |
29 #include "config.h" | 30 #include "config.h" |
30 | 31 |
31 #include "wtf/ASCIICType.h" | 32 #include "wtf/ASCIICType.h" |
32 #include "webkit/glue/webinputevent.h" | 33 #include "webkit/glue/webinputevent.h" |
33 #include "webkit/glue/event_conversion.h" | 34 #include "webkit/glue/event_conversion.h" |
34 | 35 |
35 #undef LOG | 36 #undef LOG |
36 #include "base/logging.h" | 37 #include "base/logging.h" |
37 | 38 |
38 // WebMouseEvent -------------------------------------------------------------- | 39 // WebMouseEvent -------------------------------------------------------------- |
39 | 40 |
40 WebMouseEvent::WebMouseEvent(NSEvent *event, NSView* view) { | 41 WebMouseEvent::WebMouseEvent(NSEvent* event, NSView* view) { |
41 switch ([event type]) { | 42 switch ([event type]) { |
42 case NSMouseExited: | 43 case NSMouseExited: |
43 type = MOUSE_LEAVE; | 44 type = MOUSE_LEAVE; |
44 button = BUTTON_NONE; | 45 button = BUTTON_NONE; |
45 break; | 46 break; |
46 case NSLeftMouseDown: | 47 case NSLeftMouseDown: |
47 type = [event clickCount] == 2 ? MOUSE_DOUBLE_CLICK : MOUSE_DOWN; | 48 type = [event clickCount] == 2 ? MOUSE_DOUBLE_CLICK : MOUSE_DOWN; |
48 button = BUTTON_LEFT; | 49 button = BUTTON_LEFT; |
49 break; | 50 break; |
50 case NSOtherMouseDown: | 51 case NSOtherMouseDown: |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
106 if ([event modifierFlags] & NSAlternateKeyMask) | 107 if ([event modifierFlags] & NSAlternateKeyMask) |
107 modifiers |= (ALT_KEY | META_KEY); // TODO(darin): set META properly | 108 modifiers |= (ALT_KEY | META_KEY); // TODO(darin): set META properly |
108 | 109 |
109 timestamp_sec = [event timestamp]; | 110 timestamp_sec = [event timestamp]; |
110 | 111 |
111 layout_test_click_count = 0; | 112 layout_test_click_count = 0; |
112 } | 113 } |
113 | 114 |
114 // WebMouseWheelEvent --------------------------------------------------------- | 115 // WebMouseWheelEvent --------------------------------------------------------- |
115 | 116 |
116 WebMouseWheelEvent::WebMouseWheelEvent(NSEvent *event, NSView* view) { | 117 WebMouseWheelEvent::WebMouseWheelEvent(NSEvent* event, NSView* view) { |
117 type = MOUSE_WHEEL; | 118 type = MOUSE_WHEEL; |
118 button = BUTTON_NONE; | 119 button = BUTTON_NONE; |
119 | 120 |
120 // Set modifiers based on key state. | 121 // Set modifiers based on key state. |
121 if ([event modifierFlags] & NSControlKeyMask) | 122 if ([event modifierFlags] & NSControlKeyMask) |
122 modifiers |= CTRL_KEY; | 123 modifiers |= CTRL_KEY; |
123 if ([event modifierFlags] & NSShiftKeyMask) | 124 if ([event modifierFlags] & NSShiftKeyMask) |
124 modifiers |= SHIFT_KEY; | 125 modifiers |= SHIFT_KEY; |
125 if ([event modifierFlags] & NSAlternateKeyMask) | 126 if ([event modifierFlags] & NSAlternateKeyMask) |
126 modifiers |= ALT_KEY; | 127 modifiers |= ALT_KEY; |
127 | 128 |
128 // Set coordinates by translating event coordinates from screen to client. | 129 // Set coordinates by translating event coordinates from screen to client. |
129 NSPoint location = [NSEvent mouseLocation]; // global coordinates | 130 NSPoint location = [NSEvent mouseLocation]; // global coordinates |
130 global_x = location.x; | 131 global_x = location.x; |
131 global_y = location.y; | 132 global_y = location.y; |
132 NSPoint windowLocal = [event locationInWindow]; | 133 NSPoint windowLocal = [event locationInWindow]; |
133 location = [view convertPoint:windowLocal fromView:nil]; | 134 location = [view convertPoint:windowLocal fromView:nil]; |
134 x = location.x; | 135 x = location.x; |
135 y = [view frame].size.height - location.y; // flip y | 136 y = [view frame].size.height - location.y; // flip y |
136 | 137 |
137 // Convert wheel delta amount to a number of pixels to scroll. | 138 // Of Mice and Men |
138 // Cocoa sets deltaX instead of deltaY if shift is pressed when scrolling | 139 // --------------- |
139 // with a scroll wheel, no need to do that ourselves. | 140 // |
140 static const float kScrollbarPixelsPerTick = 40.0f; | 141 // There are three types of scroll data available on a scroll wheel CGEvent. |
| 142 // Apple's documentation ([1]) is rather vague in their differences, and not |
| 143 // terribly helpful in deciding which to use. This is what's really going on. |
| 144 // |
| 145 // First, these events behave very differently depending on whether a standard |
| 146 // wheel mouse is used (one that scrolls in discrete units) or a |
| 147 // trackpad/Mighty Mouse is used (which both provide continuous scrolling). |
| 148 // You must check to see which was used for the event by testing the |
| 149 // kCGScrollWheelEventIsContinuous field. |
| 150 // |
| 151 // Second, these events refer to "axes". Axis 1 is the y-axis, and axis 2 is |
| 152 // the x-axis. |
| 153 // |
| 154 // Third, there is a concept of mouse acceleration. Scrolling the same amount |
| 155 // of physical distance will give you different results logically depending on |
| 156 // whether you scrolled a little at a time or in one continuous motion. Some |
| 157 // fields account for this while others do not. |
| 158 // |
| 159 // Fourth, for trackpads there is a concept of chunkiness. When scrolling |
| 160 // continuously, events can be delivered in chunks. That is to say, lots of |
| 161 // scroll events with delta 0 will be delivered, and every so often an event |
| 162 // with a non-zero delta will be delivered, containing the accumulated deltas |
| 163 // from all the intermediate moves. [2] |
| 164 // |
| 165 // For notchy wheel mice (kCGScrollWheelEventIsContinuous == 0) |
| 166 // ------------------------------------------------------------ |
| 167 // |
| 168 // kCGScrollWheelEventDeltaAxis* |
| 169 // This is the rawest of raw events. For each mouse notch you get a value of |
| 170 // +1/-1. This does not take acceleration into account and thus is less |
| 171 // useful for building UIs. |
| 172 // |
| 173 // kCGScrollWheelEventPointDeltaAxis* |
| 174 // This is smarter. In general, for each mouse notch you get a value of |
| 175 // +1/-1, but this _does_ take acceleration into account, so you will get |
| 176 // larger values on longer scrolls. This field would be ideal for building |
| 177 // UIs except for one nasty bug: when the shift key is pressed, this set of |
| 178 // fields fails to move the value into the axis2 field (the other two types |
| 179 // of data do). This wouldn't be so bad except for the fact that while the |
| 180 // number of axes is used in the creation of a CGScrollWheelEvent, there is |
| 181 // no way to get that information out of the event once created. |
| 182 // |
| 183 // kCGScrollWheelEventFixedPtDeltaAxis* |
| 184 // This is a fixed value, and for each mouse notch you get a value of |
| 185 // +0.1/-0.1 (but, like above, scaled appropriately for acceleration). This |
| 186 // value takes acceleration into account, and in fact is identical to the |
| 187 // results you get from -[NSEvent delta*]. (That is, if you linked on Tiger |
| 188 // or greater; see [2] for details.) |
| 189 // |
| 190 // A note about continuous devices |
| 191 // ------------------------------- |
| 192 // |
| 193 // There are two devices that provide continuous scrolling events (trackpads |
| 194 // and Mighty Mouses) and they behave rather differently. The Mighty Mouse |
| 195 // behaves a lot like a regular mouse. There is no chunking, and the |
| 196 // FixedPtDelta values are the PointDelta values multiplied by 0.1. With the |
| 197 // trackpad, though, there is chunking. While the FixedPtDelta values are |
| 198 // reasonable (they occur about every fifth event but have values five times |
| 199 // larger than usual) the Delta values are unreasonable. They don't appear to |
| 200 // accumulate properly. |
| 201 // |
| 202 // For continuous devices (kCGScrollWheelEventIsContinuous != 0) |
| 203 // ------------------------------------------------------------- |
| 204 // |
| 205 // kCGScrollWheelEventDeltaAxis* |
| 206 // This provides values with no acceleration. With a trackpad, these values |
| 207 // are chunked but each non-zero value does not appear to be cumulative. |
| 208 // This seems to be a bug. |
| 209 // |
| 210 // kCGScrollWheelEventPointDeltaAxis* |
| 211 // This provides values with acceleration. With a trackpad, these values are |
| 212 // not chunked and are highly accurate. |
| 213 // |
| 214 // kCGScrollWheelEventFixedPtDeltaAxis* |
| 215 // This provides values with acceleration. With a trackpad, these values are |
| 216 // chunked but unlike Delta events are properly cumulative. |
| 217 // |
| 218 // Summary |
| 219 // ------- |
| 220 // |
| 221 // In general the best approach to take is: determine if the event is |
| 222 // continuous. If it is not, then use the FixedPtDelta events (or just stick |
| 223 // with Cocoa events). They provide both acceleration and proper horizontal |
| 224 // scrolling. If the event is continuous, then doing pixel scrolling with the |
| 225 // PointDelta is the way to go. In general, avoid the Delta events. They're |
| 226 // the oldest (dating back to 10.4, before CGEvents were public) but they lack |
| 227 // acceleration and precision, making them useful only in specific edge cases. |
| 228 // |
| 229 // References |
| 230 // ---------- |
| 231 // |
| 232 // [1] <http://developer.apple.com/documentation/Carbon/Reference/QuartzEventS
ervicesRef/Reference/reference.html> |
| 233 // [2] <http://developer.apple.com/releasenotes/Cocoa/AppKitOlderNotes.html> |
| 234 // Scroll to the section headed "NSScrollWheel events". |
| 235 // |
| 236 // P.S. The "smooth scrolling" option in the system preferences is utterly |
| 237 // unrelated to any of this. |
141 | 238 |
142 wheel_ticks_x = [event deltaX]; | 239 CGEventRef cg_event = [event CGEvent]; |
143 delta_x = wheel_ticks_x * kScrollbarPixelsPerTick; | 240 DCHECK(cg_event); |
144 | 241 |
145 wheel_ticks_y = [event deltaY]; | 242 // Wheel Ticks are supposed to be raw, unaccelerated values, one per physical |
146 delta_y = wheel_ticks_y * kScrollbarPixelsPerTick; | 243 // mouse wheel notch. The delta event is perfect for this (being a good |
| 244 // "specific edge case" as mentioned above). For trackpads, unfortunately, we |
| 245 // don't have anything better. |
| 246 |
| 247 wheel_ticks_y = CGEventGetIntegerValueField(cg_event, |
| 248 kCGScrollWheelEventDeltaAxis1); |
| 249 wheel_ticks_x = CGEventGetIntegerValueField(cg_event, |
| 250 kCGScrollWheelEventDeltaAxis2); |
| 251 |
| 252 if (CGEventGetIntegerValueField(cg_event, kCGScrollWheelEventIsContinuous)) { |
| 253 delta_y = CGEventGetIntegerValueField(cg_event, |
| 254 kCGScrollWheelEventPointDeltaAxis1); |
| 255 delta_x = CGEventGetIntegerValueField(cg_event, |
| 256 kCGScrollWheelEventPointDeltaAxis2); |
| 257 } else { |
| 258 // Convert wheel delta amount to a number of pixels to scroll. |
| 259 static const double kScrollbarPixelsPerCocoaTick = 40.0; |
| 260 |
| 261 delta_x = [event deltaX] * kScrollbarPixelsPerCocoaTick; |
| 262 delta_y = [event deltaY] * kScrollbarPixelsPerCocoaTick; |
| 263 } |
147 | 264 |
148 scroll_by_page = false; | 265 scroll_by_page = false; |
149 } | 266 } |
150 | 267 |
151 // WebKeyboardEvent ----------------------------------------------------------- | 268 // WebKeyboardEvent ----------------------------------------------------------- |
152 | 269 |
153 // ---------------------------------------------------------------------- | 270 // ---------------------------------------------------------------------- |
154 // Begin Apple code, copied from KeyEventMac.mm | 271 // Begin Apple code, copied from KeyEventMac.mm |
155 // | 272 // |
156 // We can share some of this code if we factored it out of KeyEventMac, but | 273 // We can share some of this code if we factored it out of KeyEventMac, but |
157 // the main problem is that it relies on the NSString ctor on String for | 274 // the main problem is that it relies on the NSString ctor on String for |
158 // conversions, and since we're building without PLATFORM(MAC), we don't have | 275 // conversions, and since we're building without PLATFORM(MAC), we don't have |
159 // that. As a result we have to use NSString here exclusively and thus tweak | 276 // that. As a result we have to use NSString here exclusively and thus tweak |
160 // the code so it's not re-usable as-is. One possiblity would be to make the | 277 // the code so it's not re-usable as-is. One possiblity would be to make the |
161 // upstream code only use NSString, but I'm not certain how far that change | 278 // upstream code only use NSString, but I'm not certain how far that change |
162 // would propagate. | 279 // would propagate. |
163 | 280 |
164 namespace WebCore { | 281 namespace WebCore { |
165 | 282 |
166 static inline bool isKeyUpEvent(NSEvent *event) | 283 static inline bool isKeyUpEvent(NSEvent* event) |
167 { | 284 { |
168 if ([event type] != NSFlagsChanged) | 285 if ([event type] != NSFlagsChanged) |
169 return [event type] == NSKeyUp; | 286 return [event type] == NSKeyUp; |
170 // FIXME: This logic fails if the user presses both Shift keys at once, for
example: | 287 // FIXME: This logic fails if the user presses both Shift keys at once, for
example: |
171 // we treat releasing one of them as keyDown. | 288 // we treat releasing one of them as keyDown. |
172 switch ([event keyCode]) { | 289 switch ([event keyCode]) { |
173 case 54: // Right Command | 290 case 54: // Right Command |
174 case 55: // Left Command | 291 case 55: // Left Command |
175 return ([event modifierFlags] & NSCommandKeyMask) == 0; | 292 return ([event modifierFlags] & NSCommandKeyMask) == 0; |
176 | 293 |
(...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
636 | 753 |
637 case 59: // Left Ctrl | 754 case 59: // Left Ctrl |
638 case 62: // Right Ctrl | 755 case 62: // Right Ctrl |
639 return @"Control"; | 756 return @"Control"; |
640 | 757 |
641 default: | 758 default: |
642 ASSERT_NOT_REACHED(); | 759 ASSERT_NOT_REACHED(); |
643 return @""; | 760 return @""; |
644 } | 761 } |
645 | 762 |
646 NSString *s = [event charactersIgnoringModifiers]; | 763 NSString* s = [event charactersIgnoringModifiers]; |
647 if ([s length] != 1) { | 764 if ([s length] != 1) { |
648 return @"Unidentified"; | 765 return @"Unidentified"; |
649 } | 766 } |
650 unichar c = [s characterAtIndex:0]; | 767 unichar c = [s characterAtIndex:0]; |
651 switch (c) { | 768 switch (c) { |
652 // Each identifier listed in the DOM spec is listed here. | 769 // Each identifier listed in the DOM spec is listed here. |
653 // Many are simply commented out since they do not appear on standard Ma
cintosh keyboards | 770 // Many are simply commented out since they do not appear on standard Ma
cintosh keyboards |
654 // or are on a key that doesn't have a corresponding character. | 771 // or are on a key that doesn't have a corresponding character. |
655 | 772 |
656 // "Accept" | 773 // "Accept" |
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
934 default: | 1051 default: |
935 return [NSString stringWithFormat:@"U+%04X", WTF::toASCIIUpper(c)]; | 1052 return [NSString stringWithFormat:@"U+%04X", WTF::toASCIIUpper(c)]; |
936 } | 1053 } |
937 } | 1054 } |
938 | 1055 |
939 } // namespace WebCore | 1056 } // namespace WebCore |
940 | 1057 |
941 // End Apple code. | 1058 // End Apple code. |
942 // --------------------------------------------------------------------- | 1059 // --------------------------------------------------------------------- |
943 | 1060 |
944 WebKeyboardEvent::WebKeyboardEvent(NSEvent *event) { | 1061 WebKeyboardEvent::WebKeyboardEvent(NSEvent* event) { |
945 system_key = false; | 1062 system_key = false; |
946 type = WebCore::isKeyUpEvent(event) ? KEY_UP : KEY_DOWN; | 1063 type = WebCore::isKeyUpEvent(event) ? KEY_UP : KEY_DOWN; |
947 | 1064 |
948 if ([event modifierFlags] & NSControlKeyMask) | 1065 if ([event modifierFlags] & NSControlKeyMask) |
949 modifiers |= CTRL_KEY; | 1066 modifiers |= CTRL_KEY; |
950 if ([event modifierFlags] & NSShiftKeyMask) | 1067 if ([event modifierFlags] & NSShiftKeyMask) |
951 modifiers |= SHIFT_KEY; | 1068 modifiers |= SHIFT_KEY; |
952 if ([event modifierFlags] & NSAlternateKeyMask) | 1069 if ([event modifierFlags] & NSAlternateKeyMask) |
953 modifiers |= ALT_KEY; | 1070 modifiers |= ALT_KEY; |
954 if ([event modifierFlags] & NSCommandKeyMask) | 1071 if ([event modifierFlags] & NSCommandKeyMask) |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1001 [unmodified_str length] < kTextLengthCap) { | 1118 [unmodified_str length] < kTextLengthCap) { |
1002 [text_str getCharacters:&text[0]]; | 1119 [text_str getCharacters:&text[0]]; |
1003 [unmodified_str getCharacters:&unmodified_text[0]]; | 1120 [unmodified_str getCharacters:&unmodified_text[0]]; |
1004 } else { | 1121 } else { |
1005 LOG(ERROR) << "Event had text too long; dropped"; | 1122 LOG(ERROR) << "Event had text too long; dropped"; |
1006 } | 1123 } |
1007 [identifier_str getCString:&key_identifier[0] | 1124 [identifier_str getCString:&key_identifier[0] |
1008 maxLength:kIdentifierLengthCap | 1125 maxLength:kIdentifierLengthCap |
1009 encoding:NSASCIIStringEncoding]; | 1126 encoding:NSASCIIStringEncoding]; |
1010 } | 1127 } |
OLD | NEW |