MacOSX中实现的鼠标光标移动加速度和滚轮加速度

时间:2017-05-26 07:49:30

标签: macos events mouseevent iokit

MacOSX中实现了鼠标光标移动加速度和滚轮加速度?

在API级别,Core Graphics / Quartz Event Services提供CGEvent类型。

在应用程序方面,this Chrome change review上有许多相关且有趣的评论,并从this comment中提取:

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

在内核级别,I/O Kit是基本的驱动程序接口,我猜这个鼠标属于HID(人机接口设备)系列(IOHIDFamily)。 XNU kernel source can be seen here {}我不确定这是否完整,因为我在搜索IOHIDFamily时找不到匹配项。代码可能是here at IOHIDFamily。实际上我在IOHIPointing.cpp中找到了评论:

/*
 * 17 July  1998    sdouglas    Initial creation
 * 01 April     2002    ryepez      added support for scroll acceleration
 */

从代码中看,它在那里实现了。有人可以证实吗? 另请参阅here

IOHIPointing中的逻辑如何最终到达CGEvent?这是Core Graphics / Quartz的全部内容吗?介于两者之间?这是某种马赫事件吗?关于通用架构有什么好的概述吗?

请注意,由于正在讨论在哪里实施mouse scroll wheel acceleration in Linux / Xorg / libinput here,我想知道这个问题。

1 个答案:

答案 0 :(得分:2)

好,有问题 - 而且很重要。我应该注意到,我没有完整的信息 - 正如您已经发现的那样,其中很多都是封闭源代码。就我所知,这些是重点:

  • 您在系统偏好设置中看到的通用非Apple鼠标的鼠标设置(跟踪速度,滚动速度等)都在WindowServer内处理 - CGEvent s所在的位置。在IOHIDPointing等中进行了一些HID报告的按摩,但从我所看到的这主要是为了保持与古怪设备的兼容性。
  • 更新:(请参阅评论中的讨论)看起来WindowServer可能会通过在IORegistry条目上设置属性将加速参数传递给内核驱动程序。
  • 我相信Apple触控设备(触控板,魔术鼠标)的动力滚动实际上可能至少部分地在其各自的闭源内核驱动程序中实现,例如AppleMultitouchTrackpadHIDEventDriver
  • HID堆栈的较低级用户空间端的源代码可在IOKitUser源包中找到。这包括IOHIDManager等等。
  • 从设备到CGEvent的旅程大致是:设备 - &gt; IOHIDDevice - &gt; IOHIDInterface - &gt; IOHIDEventDriver - &gt; [IOHIDevice] - &gt; IOHIDSystem - &gt; IOHIDUserClient - &gt; IOKit内核 - 用户通信机制(内部使用Mach端口) - &gt; IOKitUser的HID部分 - &gt; WindowServer(核心图形)。
  • 您可以通过IOHIDDevice直接连接到IOHIDLibUserClient,从用户空间流程中绕过此路径。

IOKitUser源可能会更详细地回答您的一些问题。或者,如果您正在尝试做某些特定的事情,请为此打开一个新问题。