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

Side by Side Diff: webkit/glue/webinputevent_mac.mm

Issue 42607: Support for continuous scrolling devices on the Mac. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 9 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698