我们有一个应用程序,它有一个全屏视频播放器和一个浮动窗口(托盘),可以为用户提供修改视频的工具,视频播放只有一个视图,所有的绘图都发生在那里,它是一个 NSOpenGLView子类。如果用户单击托盘中的按钮,然后将托盘移动到视频视图上,我们使用 mouseEntered: 将光标 -[NSCursor set] 更新为 1 以反映用户正在绘图,但大约一秒钟后, Cocoa 将光标设置回箭头光标。
我在 -[NSCursor set] 上创建了一个符号断点,以查看它的来源,这是我得到的调用堆栈。
0 ??? 0x000000010cade785 0x0 + 4507690885,
1 Periscope HiDef4 0x00000001001d3f70 main + 0,
2 AppKit 0x00007fff4da7c55e __37+[NSDisplayCycle currentDisplayCycle]_block_invoke + 695,
3 QuartzCore 0x00007fff5b73b8c7 _ZN2CA11Transaction19run_commit_handlersE18CATransactionPhase + 49,
4 QuartzCore 0x00007fff5b73a389 _ZN2CA11Transaction6commitEv + 171,
5 AppKit 0x00007fff4e234a72 __65+[CATransaction(NSCATransaction) NS_setFlushesWithDisplayRefresh]_block_invoke + 283,
6 CoreFoundation 0x00007fff503ca737 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23,
7 CoreFoundation 0x00007fff503ca65f __CFRunLoopDoObservers + 511,
8 CoreFoundation 0x00007fff503ad128 __CFRunLoopRun + 1240,
9 CoreFoundation 0x00007fff503ac9b7 CFRunLoopRunSpecific + 487,
10 HIToolbox 0x00007fff4f68cd96 RunCurrentEventLoopInMode + 286,
11 HIToolbox 0x00007fff4f68cb06 ReceiveNextEventCommon + 613,
12 HIToolbox 0x00007fff4f68c884 _BlockUntilNextEventMatchingListInModeWithFilter + 64,
13 AppKit 0x00007fff4d93da73 _DPSNextEvent + 2085,
14 AppKit 0x00007fff4e0d3e34 -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 3044,
15 AppKit 0x00007fff4d932885 -[NSApplication run] + 764,
16 AppKit 0x00007fff4d901a72 NSApplicationMain + 804,
17 Periscope HiDef4 0x00000001001d3f92 main + 34,
18 libdyld.dylib 0x00007fff7828a015 start + 1,
19 ??? 0x0000000000000003 0x0 + 3
我尝试将实现从使用 -[NSCursor set] 和 mouseEntered: events 更改为 -[NSView addCursorRect:cursor:] 并带有整个视图边界的矩形,但这根本不会设置光标,可能是因为我们正在使用一个 NSOpenGLView 子类?
奇怪的是光标并不总是重置,如果您单击按钮并暂停然后移出托盘,我们不会得到带有上述堆栈的 -[NSCursor set],只有当您直接移动时,才有可能它与托盘更改的调整窗口框架光标大小有关,但我不确定。
我想出了一个使用 mouseMoved 的 hacky 解决方案:检查光标是什么,但它只有在用户移动光标时才有效,我宁愿弄清楚为什么我得到不需要的 -[NSCursor set] 和改为修复它。