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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webkit/glue/webinputevent_mac.mm
===================================================================
--- webkit/glue/webinputevent_mac.mm (revision 12444)
+++ webkit/glue/webinputevent_mac.mm (working copy)
@@ -24,6 +24,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <ApplicationServices/ApplicationServices.h>
#import <Cocoa/Cocoa.h>
#include "config.h"
@@ -37,7 +38,7 @@
// WebMouseEvent --------------------------------------------------------------
-WebMouseEvent::WebMouseEvent(NSEvent *event, NSView* view) {
+WebMouseEvent::WebMouseEvent(NSEvent* event, NSView* view) {
switch ([event type]) {
case NSMouseExited:
type = MOUSE_LEAVE;
@@ -113,7 +114,7 @@
// WebMouseWheelEvent ---------------------------------------------------------
-WebMouseWheelEvent::WebMouseWheelEvent(NSEvent *event, NSView* view) {
+WebMouseWheelEvent::WebMouseWheelEvent(NSEvent* event, NSView* view) {
type = MOUSE_WHEEL;
button = BUTTON_NONE;
@@ -134,17 +135,133 @@
x = location.x;
y = [view frame].size.height - location.y; // flip y
- // Convert wheel delta amount to a number of pixels to scroll.
- // Cocoa sets deltaX instead of deltaY if shift is pressed when scrolling
- // with a scroll wheel, no need to do that ourselves.
- static const float kScrollbarPixelsPerTick = 40.0f;
+ // Of Mice and Men
+ // ---------------
+ //
+ // There are three types of scroll data available on a scroll wheel CGEvent.
+ // Apple's documentation ([1]) is rather vague in their differences, and not
+ // terribly helpful in deciding which to use. This is what's really going on.
+ //
+ // First, these events behave very differently depending on whether a standard
+ // wheel mouse is used (one that scrolls in discrete units) or a
+ // trackpad/Mighty Mouse is used (which both provide continuous scrolling).
+ // You must check to see which was used for the event by testing the
+ // kCGScrollWheelEventIsContinuous field.
+ //
+ // Second, these events refer to "axes". Axis 1 is the y-axis, and axis 2 is
+ // the x-axis.
+ //
+ // Third, there is a concept of mouse acceleration. Scrolling the same amount
+ // of physical distance will give you different results logically depending on
+ // whether you scrolled a little at a time or in one continuous motion. Some
+ // fields account for this while others do not.
+ //
+ // Fourth, for trackpads there is a concept of chunkiness. When scrolling
+ // continuously, events can be delivered in chunks. That is to say, lots of
+ // scroll events with delta 0 will be delivered, and every so often an event
+ // with a non-zero delta will be delivered, containing the accumulated deltas
+ // from all the intermediate moves. [2]
+ //
+ // For notchy wheel mice (kCGScrollWheelEventIsContinuous == 0)
+ // ------------------------------------------------------------
+ //
+ // kCGScrollWheelEventDeltaAxis*
+ // This is the rawest of raw events. For each mouse notch you get a value of
+ // +1/-1. This does not take acceleration into account and thus is less
+ // useful for building UIs.
+ //
+ // kCGScrollWheelEventPointDeltaAxis*
+ // This is smarter. In general, for each mouse notch you get a value of
+ // +1/-1, but this _does_ take acceleration into account, so you will get
+ // larger values on longer scrolls. This field would be ideal for building
+ // UIs except for one nasty bug: when the shift key is pressed, this set of
+ // fields fails to move the value into the axis2 field (the other two types
+ // of data do). This wouldn't be so bad except for the fact that while the
+ // number of axes is used in the creation of a CGScrollWheelEvent, there is
+ // no way to get that information out of the event once created.
+ //
+ // kCGScrollWheelEventFixedPtDeltaAxis*
+ // This is a fixed value, and for each mouse notch you get a value of
+ // +0.1/-0.1 (but, like above, scaled appropriately for acceleration). This
+ // value takes acceleration into account, and in fact is identical to the
+ // results you get from -[NSEvent delta*]. (That is, if you linked on Tiger
+ // or greater; see [2] for details.)
+ //
+ // A note about continuous devices
+ // -------------------------------
+ //
+ // There are two devices that provide continuous scrolling events (trackpads
+ // and Mighty Mouses) and they behave rather differently. The Mighty Mouse
+ // behaves a lot like a regular mouse. There is no chunking, and the
+ // FixedPtDelta values are the PointDelta values multiplied by 0.1. With the
+ // trackpad, though, there is chunking. While the FixedPtDelta values are
+ // reasonable (they occur about every fifth event but have values five times
+ // larger than usual) the Delta values are unreasonable. They don't appear to
+ // accumulate properly.
+ //
+ // For continuous devices (kCGScrollWheelEventIsContinuous != 0)
+ // -------------------------------------------------------------
+ //
+ // kCGScrollWheelEventDeltaAxis*
+ // This provides values with no acceleration. With a trackpad, these values
+ // are chunked but each non-zero value does not appear to be cumulative.
+ // This seems to be a bug.
+ //
+ // kCGScrollWheelEventPointDeltaAxis*
+ // This provides values with acceleration. With a trackpad, these values are
+ // not chunked and are highly accurate.
+ //
+ // kCGScrollWheelEventFixedPtDeltaAxis*
+ // This provides values with acceleration. With a trackpad, these values are
+ // chunked but unlike Delta events are properly cumulative.
+ //
+ // Summary
+ // -------
+ //
+ // In general the best approach to take is: determine if the event is
+ // continuous. If it is not, then use the FixedPtDelta events (or just stick
+ // with Cocoa events). They provide both acceleration and proper horizontal
+ // scrolling. If the event is continuous, then doing pixel scrolling with the
+ // PointDelta is the way to go. In general, avoid the Delta events. They're
+ // the oldest (dating back to 10.4, before CGEvents were public) but they lack
+ // acceleration and precision, making them useful only in specific edge cases.
+ //
+ // References
+ // ----------
+ //
+ // [1] <http://developer.apple.com/documentation/Carbon/Reference/QuartzEventServicesRef/Reference/reference.html>
+ // [2] <http://developer.apple.com/releasenotes/Cocoa/AppKitOlderNotes.html>
+ // Scroll to the section headed "NSScrollWheel events".
+ //
+ // P.S. The "smooth scrolling" option in the system preferences is utterly
+ // unrelated to any of this.
- wheel_ticks_x = [event deltaX];
- delta_x = wheel_ticks_x * kScrollbarPixelsPerTick;
+ CGEventRef cg_event = [event CGEvent];
+ DCHECK(cg_event);
- wheel_ticks_y = [event deltaY];
- delta_y = wheel_ticks_y * kScrollbarPixelsPerTick;
+ // Wheel Ticks are supposed to be raw, unaccelerated values, one per physical
+ // mouse wheel notch. The delta event is perfect for this (being a good
+ // "specific edge case" as mentioned above). For trackpads, unfortunately, we
+ // don't have anything better.
+ wheel_ticks_y = CGEventGetIntegerValueField(cg_event,
+ kCGScrollWheelEventDeltaAxis1);
+ wheel_ticks_x = CGEventGetIntegerValueField(cg_event,
+ kCGScrollWheelEventDeltaAxis2);
+
+ if (CGEventGetIntegerValueField(cg_event, kCGScrollWheelEventIsContinuous)) {
+ delta_y = CGEventGetIntegerValueField(cg_event,
+ kCGScrollWheelEventPointDeltaAxis1);
+ delta_x = CGEventGetIntegerValueField(cg_event,
+ kCGScrollWheelEventPointDeltaAxis2);
+ } else {
+ // Convert wheel delta amount to a number of pixels to scroll.
+ static const double kScrollbarPixelsPerCocoaTick = 40.0;
+
+ delta_x = [event deltaX] * kScrollbarPixelsPerCocoaTick;
+ delta_y = [event deltaY] * kScrollbarPixelsPerCocoaTick;
+ }
+
scroll_by_page = false;
}
@@ -163,7 +280,7 @@
namespace WebCore {
-static inline bool isKeyUpEvent(NSEvent *event)
+static inline bool isKeyUpEvent(NSEvent* event)
{
if ([event type] != NSFlagsChanged)
return [event type] == NSKeyUp;
@@ -643,7 +760,7 @@
return @"";
}
- NSString *s = [event charactersIgnoringModifiers];
+ NSString* s = [event charactersIgnoringModifiers];
if ([s length] != 1) {
return @"Unidentified";
}
@@ -941,7 +1058,7 @@
// End Apple code.
// ---------------------------------------------------------------------
-WebKeyboardEvent::WebKeyboardEvent(NSEvent *event) {
+WebKeyboardEvent::WebKeyboardEvent(NSEvent* event) {
system_key = false;
type = WebCore::isKeyUpEvent(event) ? KEY_UP : KEY_DOWN;
« 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